8. Units Tests - tuansondinh/clean_code GitHub Wiki
"...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
"...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".
"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
- 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");
}
...
- "...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
- test and production environment have different needs -> test does "not be as efficient as production code." S.127 ... WIP
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!
- 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
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
"..tests preserve and enhance the flexibility, maintainability, and reusability of the production code. So keep your tests constantly clean."