8. Units Tests - tuansondinh/clean_code GitHub Wiki

8.1 The 3 Laws of Test Driven Development (TDD)

"...TDD asks us to write unit tests first, before we write production code." S.122

"First Law You may not write production code until you have written a failing unit test.

Second Law You may not write more of a unit test than is sufficient to fail, and not compiling is failing.

Third Law You may not write more production code than is sufficient to pass the currently failing test." S.122

"The tests and the production code are written together, with the tests just a few seconds ahead of the production code." S.123

8.2 Keeping Tests Clean

"...having dirty tests is equivalent to, if not worse than, having no tests." S.123

  • tests need to be changed as the production code evolves -> so keep the tests clean to improve maintainability

"Test code is just as important as production code".

8.3 Test Enable the -ilities

"It is unit tests that keep our code flexible, maintainable, and reusable. The reason is simple. If you have tests, you do not fear making changes to the code!" S.124

"So having an automated suite of unit tests that cover the production code is the key to keeping your design and architecture as clean as possible. Tests enable all the -ilities, because tests enable change." S.124

8.4 Clean Tests

  • readability makes a test clean
  • clarity, simplicity, and density of expression makes a test readable

BUILD-OPERATE-CHECK pattern: "The first part builds up the test data, the second part operates on that test data, and the third part checks that the operation yielded the expected results." S.127

GOOD: S.126

public void testGetDataAsXml() throws Exception { 
  makePageWithContent("TestPageOne", "test page");

  submitRequest("TestPageOne", "type:data");

  assertResponseIsXML();
  assertResponseContains("test page", "<Test");
}
...

8.5 Domain-Specific Testing Language

  • "...we build up a set of functions and utilities that make use of those APIs and that make the tests more convenient to write and easier to read." S.127
  • see example above

"This testing API is not designed up front; rather it evolves from the continued refactoring of test code..." S.127

8.6 Dual Standard

  • test and production environment have different needs -> test does "not be as efficient as production code." S.127 ... WIP

8.7 One Assert per Test / Minimize the number of asserts in a test

Rule: "...every test function in a JUnit test should have one and only one assert statement." S.130 -> better readability

  • so how to apply on example in 8.4-> split up into multiple tests -> given-when-then convention
public void testGetPageHierarchyAsXml() throws Exception { 
  givenPages("PageOne", "PageOne.ChildOne", "PageTwo");
  whenRequestIsIssued("root", "type:pages");
  thenResponseShouldBeXML(); 
}
public void testGetPageHierarchyHasRightTags() throws Exception {
 givenPages("PageOne", "PageOne.ChildOne", "PageTwo");
 whenRequestIsIssued("root", "type:pages");
 thenResponseShouldContain(
   "<name>PageOne</name>", "<name>PageTwo</name>", "<name>ChildOne</name>"
  ); 
}
  • problem: we have duplicate code, so this rule is not perfect.

BETTER: Minimize the number of asserts in a test!

8.8 Single Concept per Test

  • independent things should be also tested independently/separately "So probably the best rule is that you should minimize the number of asserts per concept and test just one concept per test function." S.132

8.9 F.I.R.S.T.

Fast Fast Tests will be run frequently -> find problems early

Independent Tests should not depend on each other, otherwise diagnosis is hard (if one fails, other will fail too)

Repeatable "If your tests aren’t repeatable in any environment, then you’ll always have an excuse for why they fail." S.132

Self-Validating "The tests should have a boolean output. Either they pass or fail." S.132

Timely "Unit tests should be written just before the production code that makes them pass." S.133

8.10 Conclusion

"..tests preserve and enhance the flexibility, maintainability, and reusability of the production code. So keep your tests constantly clean."

⚠️ **GitHub.com Fallback** ⚠️