-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Order of test runs in suite #194
Comments
I see this is an issue with reflect.TypeOf(mySuiteStruct) and it returning the methods in alphabetical order.. am I the only one with this issue? I find with end-to-end states, having separate functions for the states is helpful conceptually, but its breaking in practice |
It's nice to explicitly test building block methods first, so tests of methods utilizing those can make certain assumptions about the foundational methods and be better focused. Being able to run the tests in a suite in order of definition, as bare tests would be run, or specify a run order (without having to add garbage to the test names to force alphabetical order) would be great. |
@pkieltyka @Tauzero what's the use case to have tests run in certain order? In my opinion, tests should pass independently of heir order. Tests should keep passing if you reorder the definition or change their names. @Tauzero for what you suggest, you can simply have two different suites and run them in whatever order you prefer. |
@ernesto-jimenez IMO, test order is VERY important. It's common to build on tests sequentially, especially when previous tests have side-effects. An example I have right now is home-brew session middleware. The necessary order is:
If that stuff runs out of order, I get a slew of Alphabetically, the order becomes:
In order words...
Of course, I could consolidate this functionality into a single test function, but then what would be the point of a test "suite" at all? Why not just have a single go test block and use the assert library? I could also name the tests "Test1", "Test2", etc - but that's a book keeping headache and doesn't look great on test reports. I really think this needs to follow the standard pattern that "go test" follows, which I imagine was designed for exactly this reason. This is an awesome library otherwise. |
Here's my suggested fix... Like @pkieltyka said, the problem is inherited from You can get the natural order of method definition by sorting the pointer address in memory. Here's a quick snippet I whipped up. It seems to be reliable, but I have no idea if Go always addresses linearly.
|
@leebenson my personal opinion is that relying on test order is a bad practice, since you are basically relying on side effects for your tests to run properly. If somebody changes the order of the tests or defines a test in the middle of the file they could be breaking unrelated tests, which would make things really confusing to tests. Having a test suite can serve multiple purposes. A couple of quick examples:
Regarding The same goes with your proposed solution: are sequential addresses specified by the core and something that can be relied upon or might it change depending on the architecture or in future versions? |
@ernesto-jimenez sorry to repeat myself, but for edification of those that don't see the PR comments:
In order words...
Either way, it's the same result - we get this side-effect for "free". I don't think forcing a particular pattern on people... or indeed, straying from the |
I have an open request to go-nuts to answer the question of address safety. In the meantime, if your sort method is arbitrary and mine is arbitrary, why not accept the PR and satisfy those of us relying on it in the interim? |
@leebenson current order is the one returned by reflect, which is undocumented and subject to change in future versions. In other words, we are not setting an arbitrary order in the package. If we consider the order of tests to be important, changing for current reflect's order to a new order is a breaking change. It would break existing test suites that rely on function names to order tests. Which is a big downside. There's basically a whole set of questions to be answered with regards to test ordering: Should we guarantee certain order when running tests?Right now we do not. If the implementation of The fact that I'm yet to find the documentation that specifies If we want to guarantee an order, what should it be?There's two options:
Even if we agreed to go with your option, your solution using addresses will probably invalid since I wouldn't rely on addresses always being based in order of definition. It would be more appropriate to sort based on parsing the source code of the test file. Also, there would still be an big question: how do order tests in a suite which uses composition? |
I certainly would like to see tests ordered in the suite, even though I know the conventional thinking is to run tests in an unpredictable order. However, from so many Go code bases I've seen that write plain-jane tests with go test, the ordering helps there, and so the side-effect here as a result of I also don't think it will break other people's tests because they presumably would be depending on a random-order of tests in the suite anyways. |
@ernesto-jimenez you make some good points - if there's any chance core will de-sequence memory alloc in a future release or when targeting another arch, then obviously it's a brittle strategy and not one we can rely on. The only question is whether pointers are guaranteed to increment. If there's no reallocation of old pointer space, then there's no issue. As far as which is a preferred strategy- IMO definition order trumps alphabetical. Taking my previous example as literal, there's a much greater mental effort to having to think that You're right, of course, that the ideal scenario is to test in isolation, order be damned. However, I think that's a bit idealistic; in practice, tests usually have side-effect or require a sequence. To follow the isolation philosophy in my session class would mean either creating a session, adding data, and handling the tear-down in a single function (thus negating many of the benefits of running a "suite" of tests), creating multiple suites with many of the same set-up/teardown requirements (i.e. poor refactoring) or having each test create a new session and run that in isolation (possibly introducing bugs that occur in weird edge cases, like performing function B and C against a new session, but not A which would otherwise have already been performed in a sequential test case.) None is ideal. Function order, by contrast, is a lot easier to reason about, and pragmatic. In the real world, code has side effects and running things out of order against it can throw up strange scenarios. Not being in control of that order naturally limits the "shape" of how the code might otherwise be used in production. As @pkieltyka, there's both schools of thought used in the wild. I do a lot of front-end stuff in JS, and many of the build tools I use (mocha, gulp, grunt, webpack, etc) wouldn't make any sense out of order. It's probable my experience has been tainted/made biased by this approach, so I apologise if this is a lop-sided argument. Likewise, I've seen the die-hards saying unit tests should be isolated. But then - isn't the point of a lib like testify to abstract convention? Otherwise why don't we all just throw code into one "Test" function and save ourselves the extra keystrokes? TL,DR; if we can guarantee order by memory address, it's a free side-effect and I'd encourage opting for it. If not, everything I've said is moot, and I apologise for wasting your time :-) |
Have you seen many Go codebases that rely on order of test execution to run tests with side effects? I haven't.
I do not thing it would. The fact that memory addresses in this case are incremental is probably just a side effect of the implementation and not guaranteed to always be the case and not guaranteed to be the case in every platform.
The order right now is arbitrary, so some people might be relying on tests running based on alphabetical order. However, if
Even if the pointers were always incremental in every arch right now, as long as it's unspecified behaviour you should never rely on that, since that would be subject to change at any point.
My preferred strategy is no guaranteed order at all ;)
I think it's a totally reasonable requirement. My unit tests are all independent and never rely on ordering for side effects. In my opinion, having tests that rely on side effects to be a bad practice and would rather avoid enabling it.
You can use helper functions or setup and teardown functions.
It's go, you can use composition to reuse setup and teardown methods. Some examples can be found here: #215
If you are worried about the end to end you should have an isolated integration test. You are trying to rely on execution order to create an integration test split into several unit tests with side effects. If you want to do an integration test, do get all that code within a single isolated test rather than relying on side effects.
In Go programs, the only shape requirements within a go file are to start with the package definition, then the imports, and then the rest of the code. You can write a function that uses another function or variable in any other pace within the package. In my opinion, having code that breaks just by moving function definition around is very bad.
The purpose of this library is to reduce boilerplate and facilitate testing. In my opinion libs should when possible try to discourage bad practices. In my opinion guaranteeing test ordering would be a bad practice. I think saying unit tests should be isolated is very reasonable. That's why they are called unit tests after all, and doing so it's not that hard. |
I guess I saw a suite as the "unit" being tested, and not the individual Test* functions within it. In that paradigm, testing in order against the data created by In any case, you're obviously right - this is an implementation detail and not one specified in the Go language spec, so my address sort method cannot be relied upon in any case and is therefore moot. Thanks for engaging. |
@leebenson that's probably the issue, you were considering a test suite to be an integration test, but it's just a set of unit tests you want to group together so you can define certain setup and teardown processes. It's very useful to run the same test suite with different configurations or pre-requisites. e.g: imagine an HTTP API where you have two different roles of users, regular users and admins. Admins must be able to do everything regular users can. You might want to do a test suite and run it two times: one authenticating as a regular user and again as an admin. I'll be closing this issue. But happy to answer any questions or give you any tips you might have :) |
TLDR; ordering tests would be a nice to have feature, but for sure not critical. One can organize tests in a suite however desired, but introducing dependency between them is an extra feature and, again, would be nice to have. I guess it is assumed by most that the definition order is respected because that's how we read the file... |
I noticed the tests within a suite run in alphabetical order... why is that..? seems strange. Why wouldn't it follow the same as standard go test cases which is in the order they have been declared?
The text was updated successfully, but these errors were encountered: