|
View:
New views
7 Messages
—
Rating Filter:
Alert me
|
|
|
Sharing/Reusing Expectations across tests.Hi,
When using the TestNG testing framework, I would like to use TestNG's "dependsOnMethods" property to allow a test to rely on another test. Say my class under test, and the method being tested does two sequential events public void process() { object1.doThis(); object2.doThat(); } So say I want to write two tests (correct me if there is a better design here) to test that my class communicates with these two unrelated collaborators. Without test dependencies I would have 2 simple tests like this. @Test(groups = "unit") public void testDoThisCalled() { this.mockery.checking(new Expectations() { { oneOf(object1).doThis(); ignoring(object2).doThat(); } }); this.myClass.process(); } @Test(groups = "unit") public void testDoThatCalled() { this.mockery.checking(new Expectations() { { ignoring(object1).doThis(); oneOf(object2).doThat(); } }); this.myClass.process(); } Each test tests the object in question, but I think it gets very messy having to ignore all of the other objects. There is only two objects here, but imagine ten or more, and having to ignore them for every test it gets even more messy. Now TestNG allows you to have one test as a dependent on another test, i.e the setUp portion (@BeforeTest) is ran before the first test only so the results of the first test can be used as part of the second test. It would be good to be able to do something like @Test(groups = "unit") public void testDoThisCalled() { this.mockery.checking(new Expectations() { { oneOf(object1).doThis(); ignoring(object2).doThat(); } }); this.myClass.process(); } @Test(groups = "unit", dependsOnMethods = "testDoThisCalled") public void testDoThatCalled() { this.mockery.checking(new Expectations() { { oneOf(object2).doThat(); } }); this.myClass.process(); } Where the oneOf(object2).doThat() in the second test overwrites the ignoring(object2).doThat() in the first test, and the oneOf(object1).doThis() in test one is added to the expectations of the second test removing the need to add it again. In this second example TestNG runs test 1 and test 2 in the same sequence without reinitialising things so I would like the exectations to be carried to the second test (I hope that make sense) Again, if there is a cleaner way of doing this I would be greatly apreciated if I could be pointed in the right direction. Best Regards, Chris --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: Sharing/Reusing Expectations across tests.Obviously we can't speak for JUnit. If you want to discuss test
dependencies, you'd be better off doing that on the JUnit mailing list. 2009/7/29 <chris@...>: > Each test tests the object in question, but I think it gets very messy > having to ignore all of the other objects. That to me is a smell. If I find that my tests look like this I start asking questions about the design of the code under test: * Why do I need to ignore all but one object per test? * Why is the behaviour of the object under test so clearly split into aspects that only involve a single one of its peers? * How can I responsiblities between classes to make the objects more cohesive? > There is only two objects here, > but imagine ten or more, and having to ignore them for every test it gets > even more messy. That is an even bigger smell. If I find set-up so arduous, I ask myself questions like: * Why does this object have so many collaborators? * Is there a missing abstraction that can hide some of these collaborators from the rest of the system? --Nat -- http://www.natpryce.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: Sharing/Reusing Expectations across tests.Oops, I hit send to quickly!
But, given all that below, you can write helper methods or classes to define expectations more easily. For example: private void ignoringAllExcept(final Object significant) { context.checking(new Expectations() {{ for (Object o : allMockObjects) { if (o != significant) ignoring(o); } }}); } Where allMockObjects is defined somewhere in the test, or you could subclass Mockery to remember all the mock objects it has created. --Nat 2009/7/29 Nat Pryce <nat.pryce@...>: > Obviously we can't speak for JUnit. If you want to discuss test > dependencies, you'd be better off doing that on the JUnit mailing > list. > > 2009/7/29 <chris@...>: >> Each test tests the object in question, but I think it gets very messy >> having to ignore all of the other objects. > > That to me is a smell. If I find that my tests look like this I start > asking questions about the design of the code under test: > > * Why do I need to ignore all but one object per test? > * Why is the behaviour of the object under test so clearly split into > aspects that only involve a single one of its peers? > * How can I responsiblities between classes to make the objects more cohesive? > >> There is only two objects here, >> but imagine ten or more, and having to ignore them for every test it gets >> even more messy. > > That is an even bigger smell. If I find set-up so arduous, I ask > myself questions like: > > * Why does this object have so many collaborators? > * Is there a missing abstraction that can hide some of these > collaborators from the rest of the system? > > --Nat > > -- > http://www.natpryce.com > -- http://www.natpryce.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: Sharing/Reusing Expectations across tests.Nat,
Thanks. Basically the problem stems from the fact that the application I am developing has to fit in with an existing API, in which my core class will only be invoked with a single process() method. This process method needs to do a bunch of stuff such as reading in a file and processing the contents of it, and then notifying different listener roles of certain things. So I only have one public method in which I want to assert that a bunch of different things are happning inside it. I cant see a way of refactoring it in a way that for each step of important behaviour in the process() method can be asserted and tested without having to repeat/include all the assertions before and after. Hope that makes sense. Chris > Oops, I hit send to quickly! > > But, given all that below, you can write helper methods or classes to > define expectations more easily. > > For example: > > private void ignoringAllExcept(final Object significant) { > context.checking(new Expectations() {{ > for (Object o : allMockObjects) { > if (o != significant) ignoring(o); > } > }}); > } > > Where allMockObjects is defined somewhere in the test, or you could > subclass Mockery to remember all the mock objects it has created. > > --Nat > > 2009/7/29 Nat Pryce <nat.pryce@...>: >> Obviously we can't speak for JUnit. If you want to discuss test >> dependencies, you'd be better off doing that on the JUnit mailing >> list. >> >> 2009/7/29 <chris@...>: >>> Each test tests the object in question, but I think it gets very messy >>> having to ignore all of the other objects. >> >> That to me is a smell. If I find that my tests look like this I start >> asking questions about the design of the code under test: >> >> * Why do I need to ignore all but one object per test? >> * Why is the behaviour of the object under test so clearly split into >> aspects that only involve a single one of its peers? >> * How can I responsiblities between classes to make the objects more >> cohesive? >> >>> There is only two objects here, >>> but imagine ten or more, and having to ignore them for every test it >>> gets >>> even more messy. >> >> That is an even bigger smell. If I find set-up so arduous, I ask >> myself questions like: >> >> * Why does this object have so many collaborators? >> * Is there a missing abstraction that can hide some of these >> collaborators from the rest of the system? >> >> --Nat >> >> -- >> http://www.natpryce.com >> > > > > -- > http://www.natpryce.com > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > > > --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: Sharing/Reusing Expectations across tests.2009/7/29 <chris@...>:
> I only have one public method in which I want to assert that a bunch of > different things are happning inside it. I cant see a way of refactoring > it in a way that for each step of important behaviour in the process() > method can be asserted and tested without having to repeat/include all the > assertions before and after. It sounds like you're focusing the test on the wrong thing. I would not write a test for each "step" in the process method. Rather I'd focus it on each feature of the object as far as the client is concerned, running (and testing) the entire process method from entry to exit in each test. You might have different tests for: * possible paths through the conditionals in the process method. * error cases: what happens when there is invalid input or dependencies fail * how the process method notifies listener A * how the process method notifies listener B For the listener tests, I would only attach the relevant listener at the start of that test. That way, all other tests don't need to explicitly ignore it. For example: @Test public void notifiesSheepListenerWhenSheepProcessed() { final SheepListener sheepListener = context.mock(SheepListener.class); processor.addSheepListener(sheepListener); context.checking(new Expectations() {{ oneOf(sheepListener).sheepProcessed(); ... and expectations to make it process a sheep ... }}); processor.process(); // maybe with arguments to make it process a sheep } --Nat -- http://www.natpryce.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
Re: Sharing/Reusing Expectations across tests.The other thing I'd do is split the class into smaller component
classes and exhaustively test those, and then have a coarser grained test around the processor itself that just checks that it composes its components correctly. --Nat 2009/7/29 Nat Pryce <nat.pryce@...>: > 2009/7/29 <chris@...>: >> I only have one public method in which I want to assert that a bunch of >> different things are happning inside it. I cant see a way of refactoring >> it in a way that for each step of important behaviour in the process() >> method can be asserted and tested without having to repeat/include all the >> assertions before and after. > > It sounds like you're focusing the test on the wrong thing. I would > not write a test for each "step" in the process method. Rather I'd > focus it on each feature of the object as far as the client is > concerned, running (and testing) the entire process method from entry > to exit in each test. > > You might have different tests for: > > * possible paths through the conditionals in the process method. > * error cases: what happens when there is invalid input or dependencies fail > * how the process method notifies listener A > * how the process method notifies listener B > > For the listener tests, I would only attach the relevant listener at > the start of that test. That way, all other tests don't need to > explicitly ignore it. For example: > > @Test > public void notifiesSheepListenerWhenSheepProcessed() { > final SheepListener sheepListener = context.mock(SheepListener.class); > processor.addSheepListener(sheepListener); > > context.checking(new Expectations() {{ > oneOf(sheepListener).sheepProcessed(); > > ... and expectations to make it process a sheep ... > }}); > > > processor.process(); // maybe with arguments to make it process a sheep > } > > --Nat > -- > http://www.natpryce.com > -- http://www.natpryce.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
|
|
|
| Free embeddable forum powered by Nabble | Forum Help |