Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<h2>Pattern</h2> <p>Interesting question. First of all - my ultimate test pattern configured in IDE:</p> <pre><code>@Test public void shouldDoSomethingWhenSomeEventOccurs() throws Exception { //given //when //then } </code></pre> <p>I am always starting with this code (smart people call it <a href="http://blog.objectmentor.com/articles/2008/11/27/the-truth-about-bdd" rel="noreferrer">BDD</a>). </p> <ul> <li><p>In <code>given</code> I place test setup unique for each test. </p></li> <li><p><code>when</code> is ideally a single line - the thing you are testing. </p></li> <li><p><code>then</code> should contain assertions.</p></li> </ul> <p>I am not a <em>single assertion</em> advocate, however you <em>should</em> test only single aspect of a behavior. For instance if the the method should return something and also has some side effects, create two tests with same <code>given</code> and <code>when</code> sections.</p> <p>Also the test pattern includes <code>throws Exception</code>. This is to handle annoying checked exceptions in Java. If you test some code that throws them, you won't be bothered by the compiler. Of course if the test throws an exception it fails.</p> <h2>Setup</h2> <p>Test setup is very important. On one hand it is reasonable to extract common code and place it in <code>setup()</code>/<code>@Before</code> method. However note that when reading a test (<strong>and readability is the biggest value in unit testing!</strong>) it is easy to miss setup code hanging somewhere at the beginning of the test case. So relevant test setup (for instance you can create widget in different ways) should go to test method, but infrastructure (setting up common mocks, starting embedded test database, etc.) should be extracted. Once again to improve readability.</p> <p>Also are you aware that JUnit creates new instance of test case class per each test? So even if you create your CUT (<em>class under test</em>) in the constructor, the constructor is called before each test. Kind of annoying.</p> <h2>Granularity</h2> <p>First name your test and think what use-case or functionality you want to test, never think in terms of:</p> <blockquote> <p><em>this is a <code>Foo</code> class having <code>bar()</code> and <code>buzz()</code> methods so I create <code>FooTest</code> with <code>testBar()</code> and <code>testBuzz()</code>. Oh dear, I need to test two execution paths throughout <code>bar()</code> - so let us create <code>testBar1()</code> and <code>testBar2()</code></em>. </p> </blockquote> <p><code>shouldTurnOffEngineWhenOutOfFuel()</code> is good, <code>testEngine17()</code> is bad.</p> <h2>More on naming</h2> <p>What does the <code>testGetBuzzWhenFooIsNullAndFizzIsNonNegative</code> name tell about the test? I know it <em>tests</em> something, but why? And don't you think the details are too intimate? How about:</p> <pre><code>@Test shouldReturnDisabledBuzzWhenFooNotProvidedAndFizzNotNegative` </code></pre> <p>It both describes the input in a meaningful manner and your intent (assuming <em>disabled buzz</em> is some sort of <code>buzz</code> status/type). Also note we no longer hardcode <code>getBuzz()</code> method name and <code>null</code> contract for <code>Foo</code> (instead we say: <em>when <code>Foo</code> is not provided</em>). What if you replace <code>null</code> with <em>null object pattern</em> in the future?</p> <p>Also don't be afraid of <em>20 different test methods for <code>getBuzz()</code></em>. Instead think of 20 different use cases you are testing. However if your test case class grows too big (since it is typically much larger than tested class), extract into several test cases. Once again: <code>FooHappyPathTest</code>, <code>FooBogusInput</code> and <code>FooCornerCases</code> are good, <code>Foo1Test</code> and <code>Foo2Test</code> are bad.</p> <h2>Readability</h2> <p>Strive for short and descriptive names. Few lines in <code>given</code> and few in <code>then</code>. That's it. Create builders and internal DSLs, extract methods, write custom matchers and assertions. The test should be even more readable than production code. Don't over-mock.</p> <p>I find it useful to first write a series of empty well-named test case methods. Then I go back to the first one. If I still understand what was I suppose to test under what conditions, I implement the test building a class API in the meantime. Then I implement that API. Smart people call it TDD (see below).</p> <h2>Recommended reading:</h2> <ul> <li><a href="http://rads.stackoverflow.com/amzn/click/0321503627" rel="noreferrer">Growing Object-Oriented Software, Guided by Tests</a></li> <li><a href="http://rads.stackoverflow.com/amzn/click/1558608680" rel="noreferrer">Unit Testing in Java: How Tests Drive the Code</a></li> <li><a href="http://rads.stackoverflow.com/amzn/click/0132350882" rel="noreferrer">Clean Code: A Handbook of Agile Software Craftsmanship</a></li> </ul>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload