Hi all,Just to confirm: junit does use a new fixture object for each test (or example). The following test prints "1 1". I am currently checking that the same behaviour occurs in a concordion spec using examples.import org.junit.Test;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created by tim on 23/11/15.
*/
public class TestIndependance {
private AtomicInteger i = new AtomicInteger(0);
@Test
public void testOne() {
System.err.println(i.addAndGet(1));
}
@Test
public void testTwo() {
System.err.println(i.addAndGet(1));
}
}On 23 November 2015 at 18:29, Tim Wright <t...@tfwright.co.nz> wrote:Hi Andrew,TLDR version: it might be best *not* to use the example functionality in your test cases.I've often wondered why jUnit's BeforeClass and AfterClass annotations are static - sometimes it causes issues. I believe that the rationale is that we shouldn't be sharing data between tests because it risks creating ordering effects - it's better to recreate all test data for each test case (or each "example" as we call them in concordion).In fact, Martin Fowler (one of the jUnit authors) writes about this exact point:I've also done some research and discovered that jUnit creates a new test object for *each* test case. It used to be that a concordion test had exactly one test case - now we have one per example. So a non-static before spec annotation might not work for you. Note that I have not observed this in my own jUnit usage so the jUnit behaviour might have changed over time.eg: apparently the following code prints "0 0 0":public class TestJunit { int count = 0; @Test public void testInc1(){ System.out.println(count++); } @Test public void testInc2(){ System.out.println(count++); } @Test public void testInc3(){ System.out.println(count++); } }However, pragmatically :)
- I do like the idea of beforeProcessingSpecification and afterProcessingSpecification annotations. These are like Spring's @PostConstruct and @PreDestroy annotations. We could even have concordion:example="beforeProcessingSpecification" tags in the spec - like concordion:example="before" tags. However, I've looked at the code (including our junit integration) and it might be tricky to do cleanly.
- You are right that this.getClass().getName() will *not* work the same static methods as it does in non-static methods. You can get around this by having the static methods take a class parameter. But that won't work for @BeforeClass methods where you can't pass parameters. Sigh.
- One way to get around the @before annotation working differently is to create lazy initialisers. That way the initializers are only invoked once. Something like the following - but I can't figure out a good @AfterClass version.
public synchronized void before() {if (!initialized) {initialised= true;... do whatever}
- If you only have one example (ie: don't use the concordion:example tag) then @Before and @After will work as they did before :)
Hope that helps,Tim--On 23 November 2015 at 14:19, Andrew <andrew...@xtra.co.nz> wrote:--Currently we do a number of setup/teardown actions for the entire specification using the Junit @Before and @After methods, crucially we use @Before in the specification to setup test data belonging to the specification, and @After in the base fixture to ensure this data is cleaned up, the browser is closed, etc.Now that the @Before and @After methods are called for each example this isn't working. I had a quick look at @BeforeClass/AfterClass but:
- I don't believe tricks like using "this.getClass().getName()" to get the name of the test class from the base fixture will work on a static method
- If I changed the test data store to a static then I'm concerned about this bleeding into other tests, especially if we start running tests in parallel
Any suggestions on how to work around this?My current thought is to create two new annotations @BeforeProcesssingSpecification and @AfterProcesssingSpecification and ensure any method decorated with those get called at the appropriate time. This would be better than @Before/After as currently if any errors are thrown in @Before then the specification is not generated (this might be a by product of using @FailFast though, I haven't looked at the issue to closely).CheersAndrew
You received this message because you are subscribed to the Google Groups "concordion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to concordion+...@googlegroups.com.
To post to this group, send email to conco...@googlegroups.com.
Visit this group at http://groups.google.com/group/concordion.
To view this discussion on the web, visit https://groups.google.com/d/msgid/concordion/a18c01ce-0533-4aed-a05e-b6223e724c86%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "concordion-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to concordion-de...@googlegroups.com.
To post to this group, send email to concord...@googlegroups.com.
Visit this group at http://groups.google.com/group/concordion-dev.
To view this discussion on the web, visit https://groups.google.com/d/msgid/concordion-dev/CAJifTyrz8HZ4-8GL%2BMH2PQpkfC5Svqeh2fpxRDQr7qJwn2nRTw%40mail.gmail.com.
That would be fine if the code was in the fixture, but the majority of this code is in a base class all the test classes inherit from, eg we have a test data store that keeps track of any data added for the tests and cleans up after they've finished - which would still work except for the fact that we create this data once in an @before method in the fixture for all the examples to share rather than as each example is about to be executed. A lot of that data is read only data that will not change with each example so the approach works well for us.
Other code in the base fixtures @before/after methods uses this.getclass().getname() for things like setting up logging to a unique file per test and that just won't work with @Before/AfterClass static methods
I would be happy to but if current behaviour is changed so that a new fixture object is created for each example then I'm not sure how much benefit it would provide (for my current needs) as unless I'm using statics I'd loose any state information rendering the exercise pointless.
I can't help thinking that creating a new fixture object per example could lead to some strange behaviour - this would need to be really well documented. When you're dealing with a junit test suite and each test is annotated with @test it makes sense that each test is standalone. When you're dealing with a specification and fixture the lines become very blurred and I think you may end up making developing these tests more complicated than it needs to be. That said I'd really need to try it out and see what impacts it had.
I also like to keep things as simple as possible so that it's easier to cross train testers so that they can help develop the tests so I have a vested interest in keeping things simple :-)
To maintain what they currently have, couldn't they just change to using @BeforeClass/@AfterClass and static state?That would be fine if the code was in the fixture, but the majority of this code is in a base class all the test classes inherit from, eg we have a test data store that keeps track of any data added for the tests and cleans up after they've finished - which would still work except for the fact that we create this data once in an @before method in the fixture for all the examples to share rather than as each example is about to be executed. A lot of that data is read only data that will not change with each example so the approach works well for us.
Other code in the base fixtures @before/after methods uses this.getclass().getname() for things like setting up logging to a unique file per test and that just won't work with @Before/AfterClass static methods
Thread.currentThread().getStackTrace()[1].getClassNam
e();
MethodHandles.lookup().lookupClass()
There is some performance penalty to both of these, so it might be
worth trialling which is faster.From your other post: I also like the idea of @BeforeSpecification and @AfterSpecification annotations (and possibly also @BeforeSuite and @AfterSuite for the whole Concordion suite). This might be something you could try out as an extension and then report back on it?I would be happy to but if current behaviour is changed so that a new fixture object is created for each example then I'm not sure how much benefit it would provide (for my current needs) as unless I'm using statics I'd loose any state information rendering the exercise pointless.
I'm not adverse to changing the tests to work with a new fixture object per example but I'm getting very concerned that the approach/framework that I've been building at MSD will be incompatible with the example command. For example, how would you suggest we could use the logback extensions to get a separate log file per specification when have several examples? (You'll probably need review some of my code to answer that one...)
- Perhaps we need the flexibility of something like the @TestInstance(PER_CLASS) annotation you mentioned?
- Or if there was always one fixture object created for the specification (plus a new one for each example) and we had the @Before/AfterSpecificaion support this might solve some of my issues.
Andrew
Thread.currentThread().getStackTrace()[1].getClassName();MethodHandles.lookup().lookupClass()--
You received this message because you are subscribed to the Google Groups "concordion-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to concordion-de...@googlegroups.com.
To post to this group, send email to concord...@googlegroups.com.
Visit this group at http://groups.google.com/group/concordion-dev.
To view this discussion on the web, visit https://groups.google.com/d/msgid/concordion-dev/be40d947-697d-4d1f-8412-226cdb5ed082%40googlegroups.com.