Test Class Organization
09Feb10
Hi there
Just though I d share this
this is the way I ve been organizing my test code as of late
public class MyClassTests { public class Given_a_context { [Fact] public void When_somthing_happens_Then_result() { throw new NotImplementedException(); } //............... } public class Given_a_different_context { [Fact] public void When_somthing_happens_Then_result() { throw new NotImplementedException(); } //............... } }I like this because you can still easily find the class name with resharper
you can also separate the contexts you are testing in a more clean way
this works out good for me most of the times, even when you are inheriting
from a base test class.
It also reads well in the Test runner.
Any comments?Advertisement
Filed under: Uncategorized | 9 Comments
Tags: unit-testing
Onya for sharing…
Based on http://haacked.com/archive/2008/08/24/introducing-subspec.aspx and http://www.code-magazine.com/Article.aspx?quickid=0805061
and http://www.codethinked.com/post/2009/03/08/Beginning-Mocking-With-Moq-3-Part-1.aspx
I’m using use a Context/Spec stylee. I find it breaks stuff up in the code and in your head much better than a slab of code with 3x comments or line breaks into AAA.
More stuff I found: (by googling aaa context/specification)
http://www.pluralsight.com/community/blogs/starr/archive/2009/02/27/some-alternative-ways-of-reading-context-specification.aspx + comments
http://elegantcode.com/2009/02/27/some-alternative-ways-of-reading-contextspecification/ + comments
http://groups.google.com/group/behaviordrivendevelopment/browse_thread/thread/5bffac19e28e5f12/2ef57e408fb38d0f?show_docid=2ef57e408fb38d0f
Nice example: http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/24/arrange-act-assert-and-bdd-specifications.aspx
Or, as you use: http://www.clariusconsulting.net/blogs/kzu/archive/2009/10/01/171565.aspx
(Esp see the TD.NET spec renderer)
hehe, the two first ones are actually the same article
The problem I find with the aproach explained there is that to find the tests I want the test files to be called something like MyUnitTests (where MyUnit is the class under tests) as opposed to: When_an_item_is_added as a class name, it just hard to find a test quickly, but the rest, yeah I agree with that
Sorry didnt see this till now
I was aware the second article was linked from the first but wanted to be sure that it didnt get skimmed over.
I use CR but suspect R# can also handle the other arrangement if you do a class or method search rather than a file one. But I take the general point of the findability of something being an important consideration in the naming.
I consider XYZClassTests orgainisation (assumption of 1:1:1 class:test class:test file) to be an antipattern).
Resubmitting so I get followups!
If you say something like “I consider XYZClassTests organisation an Antipattern”, I m sure you expected the Why? or actually in what particular situations
Regarding discover-ability of the class/ method of course you can do that with R# ( and I think even plain VS does that in the 2010 version) however finding OrderServiceTests is pretty intuitive compared to Given_an_initialised_OrderService your eyes just know what to look for in the first case.
Anyway, this is a matter of taste, as long as the codebase is consistent, I d say it s ok.
Looking again – I scanned a little too quickly when making the last comment (I assumed there wasnt nesting of classes). With the nesting of classes you’re bringing in most of what I’m talking about. In other words, you’re not implying a 1:1:1 ratio, you have a 1:1:n (class:testgroup:testclass) instead. I’d argue that while a lot of your testing is going to be (and should be) specific to a class (a class being the most common Unit), having a less rigid way of grouping (specification/concern hierarchy[1]/observations) fits the way I like to look at things better (To be pejorative, I’m not testing a class to tick a box, I’m writing specifications for a variety of concerns managed by related clumps of classes – even if in many cases they are just one class)
[1] You dont preclude this in your arrangement, but making it MyClassTests ties it a) to a class b) to thinking “I wrote my class, now I’m testing my class” instead of doing something higher level
Immediately after reading AOUT (but before I read the BDD stuff, xUTP and PragUnitTesting) I would probably not have split hairs about this.
In Context/Spec, you can use namespaces and nested classes to accomplish the grouping you do via the MyClassTests grouping class too (And I do – I have a Specifications folder per project and there’s a hierarchy of cs files with grouped specs in those, including use of folders as appropriate – and the arrangment does not necessarily mirror the foldering [based on namespacing] that the actual SUT has)
Another thing I like about Context/Specification is that the EstablishContext/Because/Observation structuring is very natural and a nice extension to AAA (and doesnt require comments or putting 2 blank lines between the A regions) (Or #regions around each of the As
) – it really helps you to think.
I think it’s fair to say we’re not a million miles apart on this – it’s just a slightly different philosophy. It’s definitely a long way from:
VS “Generate tests for this class” menu option (because our boss told us we need to tick this box to get the cookie)
class A
{
A
B
}
class ATests
{
TestA()
Arrange
Act
Assert
TestB()
Arrange
Act
Assert
}
Or (AOUT IIRC – which doesnt break out the context as explicitly as ‘yours’ or ‘mine’):
class A
{
}
class ATests
{
MethodName_StateUnderTest_Behavior()
Arrange
Act
Assert
MethodName_StateUnderTest_Behavior()
Arrange
Act
Assert
MethodName_StateUnderTest_Behavior()
Arrange
Act
Assert
}
My “final” (it never is!) arrangement is:
(top level – the code)
class X
class XFactory
class Y
class Z
class ZHelper
namespace Z.Linq
class ZExtensions
(Under Specifications folder/namespace)
class/namespace XYSpecifications
class XYZSpecificationBase
EstablishContext
v light smattering of helpers
class When_XStuff
EstablishContext?
Arrange
Because
Act
Observation*
Assert
class When_YStuff
EstablishContext?
Arrange
Because
Act
Observation*
Assert
class When_ZStuff
EstablishContext?
Arrange
Because
Act
Observation*
Assert
class/namespace XY_Z_Specification
class When_ZStuff
EstablishContext?
Arrange
Because
Act
Observation*
Assert
Oh no, it stripped my indentation! Looks pretty crap but hopefully you’ll be able to pull out my points…
A related post…
http://elegantcode.com/2010/03/01/an-evolution-of-test-specification-styles-my-journey-to-mspec/