-
Notifications
You must be signed in to change notification settings - Fork 744
Several SetUpFixtures at the same level may be active at the same time #1474
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Perhaps you could explain why this a problem for you. I don't think the order of when OneTimeSetUp methods are invoked is specified right now. Only that they'll be called once before any fixtures in the same namespace are executed. |
We have system tests that use the SetUpFixtures to manage services needed during tests in a namespace. Several namespaces may contain the same service, i.e. will allocate the same listening port. In NUnit 2.6.2 this worked fine, and no two setup fixtures on the same level were active at the same time. I don't fancy redesigning the service hosting and database setup for our system tests as part of the upgrade to NUnit 3.2.1, especially since it was not listed as a breaking change. |
It's not exactly a breaking change, which is why it isn't listed. A breaking change is a change in NUnit's previously defined behavior. In this case, running tests by walking the namespace tree depth-first was simply an implementation detail, albeit one that proved useful to you. I do think this would be a useful feature. We do not currently consider a SetUpFixture to be "active" or "inactive" as you have indicated, but it seems to be a useful concept. It would be easy to implement for your specific situation, but gets more complicated as we consider the interaction of this feature with tests run in parallel. Since a namespace may have multiple SetUpFixtures, it would be possible for them to have conflicting parallel scopes. We will have to decide how to resolve those. I think some sort of spec will be called for. |
We have case when in global we have to prepare SeeTest client, then in iPhone, iPad, Android namespaces we have to open devices for client. Then we have some tests in namespaces iPhone.Auth, etc. which needs app to be authenticated (those outside Auth namespace needs app to be unauthenticated). NUnit first executes iPhone.Auth.Setup, then iPhone tests, then iPhone.Auth tests and at the end iPhone.Auth.TearDown. I was expecting it to work like DFS. |
While we marked this as a feature and added it to our backlog, it may not be clear to everyone what that means: that we accept this as something we will fix, change or add. Maybe we should change "Backlog" to "Accepted" :-) |
I understand what Backlog means. I just wanted to give you other example of use case. We found workaround for this, but will wait for this to be implemented to use it. |
Does your use case involve any parallel execution of child tests or is just an issue of sequencing what we run? |
Some thoughts on the design of this... This is somewhat related to #1239 but is a bit simpler. If no parallel execution is involved and everything runs on the non-parallel queue, then all we have to do is run children before doing anything else. Since there's only one thread, no two SetUpFixtures can be active at the same time... with one small exception. The exception is that some child tests may require the STA, which involves a separate queue. Execution may need to switch back and forth between the two queues - possibly several times - in order to complete the work. But there is no way to prevent tests other queued tests like other SetUpFixtures from running when we switch queues - at least not currently. This leads me to think of a workaround that @tso-blstream and others may want to try: running the tests using the --workers:0 option. With that option no queues are used, no switching occurs and I believe the order of running is compatible with NUnit 2. When some child tests may be parallel, all bets are off. Since the child of a parallel test may declare itself non-parallel - and vice versa - we're switching back and forth among our various queues all the time in order to get the work done. When one queue is exhausted, we switch to another one, and we are done when there is no work to do anywhere. I'm thinking that it may be necessary, in the case of a non-parallel fixture with parallel children, to establish a private set of queues just for those children. Since it would take looking at all the children to detect this situation, it may mean that we set up separate queues and workers (or use a pool) for each test suite and fixture! |
I have tested it with |
NOTE: This is out of date, see later comments. Proposed design ... looking for comments from @nunit/core-team, @nunit/framework-team and anyone else interested in this feature.
Ideally, we would all stand around a white board and talk about this. Lacking that... pleas comment here. |
I don't see a problem with it, but right now I can't imagine writing tests with some kind of global state so I'd never use it. Even my integration tests stay out of each other's way. |
@jnm2 The use case here is for SetUpFixture. Since we don't give you any way to access instance information for a SetUpFixture from a TestFixture or TestCase, use of some sort of global state seems to be fairly common. I definitely agree that it is both possible and desirable to structure tests so that this is not necessary! |
Here's a simpler case that we may want to resolve first... Let's say you have a Eventually, the dispatcher will exhaust the non-parallelizable queue and switech execution to the parallelizable queue and those test cases will get run. However, there may be other fixtures and their test cases on that queue and they will be run even though the original non-parallelizable fixture is still active. This is essentially caused by the same internal issue as the initial problem: we do not distinguish between the active state and the running state. That is, there is no way to consider a fixture as active except when it's code is executing. However, from a user point of view, it is seen as active from the first one-time setup to the final one-time teardown. I'm going to give this a think and if it seems like it can be resolved more simply than this issue, I'll create a new issue that we may want to work on first. |
Your design looks okay, but it is very complex. Is there no way to simplify by stepping back and changing the way we do the initial queuing of the tests? Probably not, I am saying this without having looked at that code in ages, but I always hate to see additional complexity 😄 |
Agreed. Have you looked at #2143, which identifies a simpler issue that works toward the problem? |
I think PR #2151, which resolves issue #2143, takes care of the problem of setup fixtures running together and eliminates the need for specifying "Groups" of fixtures which may not run together even though they are parallelizable. I'll lay out what I think will be the effect of #2151 in several different situations and we can decide whether I'm right!
namespace A
{
[Parallelizable]
public class TopLevelFixture{ }
}
namespace A.B
{
[NonParallelizable] // or leave as default
public class ConflictingFixture1 { }
[NonParallelizable] // or leave as default
public class ConflictingFixture2 { }
} Let's discuss this after the review and merge of #2151. You'll have to understand how that works in order to make sense of this one. 😄 |
I agree that this should be considered complete with the changes in #2151. |
In that case... |
I'm quite happy with how this turned out. It's a much simpler solution than I originally envisioned. We may need to get more complicated to handle dependencies, but for now this is pretty good. |
When having multiple SetUpFixtures in a at the same level of test assembly all OneTimeSetUp methods are invoked before the first test is invoked.
The following is an excerpt from the trace of an execution of a test assembly with a setup fixture in NUnitTest.NamespaceA and one in NUnitTest.NamespaceB that shows how both setups are executed before the first test in NamespaceA is executed:
NUnitTest.zip contains a set of tests that reproduces the issue.
TestRunAndTrace.zip contains output and internal trace from running the tests above using NUnit3-console 3.2.1.
The text was updated successfully, but these errors were encountered: