Using English to describe a test is quite a challenge. It is demonstrated in the various styles present in the community. My naming conventions, much like my development style, change constantly.
When I first began TDD, my names looked something like this:
public void MethodATest()
Look familiar? What does this test? Well, it gives me a new method. It tells me I have to test all the functions of this method in one test. It does not give business value and does not give any clues when it fails.
This methodology did not last long -- my tests were too large, too complex and tested too many things. When I had a failing test, I had some idea what was wrong because I remembered the method, but my tests did not evolve with my code.
Eventually, my next naming convention looked a little more like this:
public void MethodADoesThis()
or
public void MethodADoesThisWithThat()
or
public void MethodADoesThisWithThatWhenThisIsTrue()
(sometimes this was: public void WhenThisIsTrueMethodADoesThisWithThat())
Although this naming was more descriptive, it was slightly ambiguious, drove too much design in a single test and was not easily read.
The anatomy of a test is basic, there is a setup of preconditions (context), execution of the code (call method), and then verification process (Assert or Verify).
What if our name told us what to put in each part. Would you know how to write it? Would you know what its testing?
Back in February, Aaron made a post about loosly coupled mocks. His naming convention is great. Its simple, has clear rules and forces you to think about what you are testing. It not only follows the anatomy of the test, but puts you in your test before you write it.
What it looks like:
public void Method_Context_Expectation()
So, for the simple hello world test:
public void GreetTheWorld_Always_CallsConsoleWriteLine
Always is a weird context right? Well, its true and writing it helps understand what you are designing.
Now, what if we want to add a condition to calling GreetTheWorld?
Say we only greet the world, if the world exists:
public void GreetTheWorld_WorldExists_CallsConsoleWriteLine
public void GreetTheWorld_WorldDoesNotExist_DoesNotCallConsoleWriteLine
This naming convention also helps us understand when to use SetupResult instead of expectations. In the methods above, we are using the world as context, and the console as verification so we would say SetupResult.For(theWorld.Exists) instead of expecting it -- we don't want our test to fail from context, only when our expectations are not met.
Another nice thing about this convention is detecting smells in my design. If I have 10 methods for GreetTheWorld, because there are many contexts or expectations, I'd know GreetTheWorld had too many responsibilities.
Who would have thought a simple naming convention could have helped so much, thanks Aaron -- or rather the unnamed person Aaron stole this from :P
{ 0 komentar... read them below or add one }
Posting Komentar