{"id":12181,"date":"2016-03-03T11:01:15","date_gmt":"2016-03-03T09:01:15","guid":{"rendered":"https:\/\/mozaicworks.com\/?p=8929"},"modified":"2023-09-15T14:57:39","modified_gmt":"2023-09-15T11:57:39","slug":"software-craftsmans-tools-unit-testing","status":"publish","type":"post","link":"https:\/\/mozaicworks.com\/blog\/software-craftsmans-tools-unit-testing","title":{"rendered":"Software Crafer’s Tools: Unit Testing"},"content":{"rendered":"\n
This article was first published in Today Software Magazine, no 12<\/a>. Below it\u2019s the full version. <\/em>The authors are: Alexandru Bolboaca<\/a> and Adrian Bolboaca.<\/a><\/em><\/em><\/p>\n\n\n\n The Problem<\/strong><\/p>\n\n\n\n Imagine the following situation: a team has developed for 6 months a great product that immediately sells. Users show their passion for the product by asking new features. If the team does not deliver the new features fast enough, their happiness will decrease. They might even switch to a competing application. The team must deliver quickly.<\/p>\n\n\n\n Unfortunately, it takes weeks or months to validate the product completely, without accounting the time for bug-fixing. The team cannot deliver in time if the product is tested completely. What can they do?<\/p>\n\n\n\n The most common strategies are:<\/p>\n\n\n\n All these strategies translate into temporarily decreasing the care for the product in order to obtain faster delivery. Unfortunately, the technical teams in the scenarios above are taking business risks. Their major risk is missing the impact on certain application areas and delivering bugs. This can turn into:<\/p>\n\n\n\n What if… <\/i><\/b><\/p>\n\n\n\n The team could validate the whole application in hours and not in weeks or months?<\/p>\n\n\n\n What if each programmer could learn after each code change, in minutes, that nothing else was affected (with 80+% probability)?<\/p>\n\n\n\n The article on Software Craft mentions the main idea of the movement: a software crafter can deliver quality under pressure. Given the circumstances above, a software crafter should deliver new features in the given time with as few bugs as possible. How few? Less than 10 per release. This is a conservative number. Agile methods (including Scrum) demand 0 known bugs at the end of each 2-3 weeks sprint, after a validation by testers.<\/p>\n\n\n\n But any software application has bugs! <\/i><\/b><\/p>\n\n\n\n The name \u201cbug\u201d is a euphemism for mistake. Mistakes are normal in any human activity, including software development.<\/p>\n\n\n\n How can we reduce the mistakes and their impact? Unit testing is a tool that can help, but it is not the only one. Others are: code review, pair programming, reducing the number of lines of code, design by contract.<\/p>\n\n\n\n Unit testing <\/i><\/b><\/p>\n\n\n\n Unit testing means writing code, named testing code, that validates the production code. Testing most of the application becomes automatic.<\/p>\n\n\n\n History: programmers often believe that unit testing is a new practice. The reality is that unit testing was used from the times of mainframe computers and punch cards. Back then, debugging was very difficult because it implied reading tens of meters of sheets of paper printed with the program results and execution information. Automated tests that ran at the same time as the program gave much more information about the source of the mistakes.<\/p>\n\n\n\n What about testers? They are often afraid that they’ll lose their work once automated testing is introduced. The truth is that testers become much more important because they’re the only ones who can discover hidden problems, difficult or impossible to find with automated tests. They help increase the probability of correctness from 80+% to almost 100%.<\/p>\n\n\n\n Unit tests have a few important properties:<\/p>\n\n\n\n To be fast, unit tests often use so called \u201ctest doubles\u201d. Similar with plane pilots that learn in a simulator before driving a plane, unit tests use pieces of code that look like the production code but are only used for testing. Stubs and mocks are the most common test doubles; others exist but are less used.<\/p>\n\n\n\n A stub is a test double that returns values. A stub is similar with a very simple simulation: when a button is pressed, a value appears. A manually written stub looks like this:<\/p>\n\n\n\n A mock is a test double that validates collaboration between objects. Mocks validate method calls with certain parameters, for a certain number of times. A mock can be used to validate method calls for methods that don’t return values.<\/p>\n\n\n\n Test doubles can be created using special frameworks, like mockito for Java (ports exist for other languages) or moq for .NET.<\/p>\n\n\n\n Test doubles were initially used only in places where controlling the system was very hard or where tests were slow due to calls to external systems. In time, test doubles became more used in all unit tests, resulting in the \u201cmockist\u201d way of testing. The article Mocks aren’t stubs<\/a> by Martin Fowler has much more details.<\/p>\n\n\n\n Unit tests are written by a programmer, during the implementation of a feature.<\/p>\n\n\n\n Unfortunately, the most common way of writing tests is sometime after the implementation was finished. The usual result is that the tests are not written or they are written based on the existing implementation and not on the correct application behavior.<\/p>\n\n\n\n Test First Programming is a way to write tests that has the following steps:<\/p>\n\n\n\n By applying Test First Programming, the developers make sure that they write unit tests and they test the required behavior.<\/p>\n\n\n\n Test Driven Development (TDD)<\/a> can be considered a third way of writing tests.<\/p>\n\n\n\n Actually, TDD is a way of making incremental design.<\/p>\n\n\n\n Writing tests takes a long time! <\/i><\/b><\/p>\n\n\n\n Case studies and personal experiences show that the time spent just to develop a feature is indeed increasing when adopting unit testing. Same studies show the time spent to maintain the product decreases considerably, showing that unit testing can be a net optimization in the total development time.<\/p>\n\n\n\n However, no study can change the programmer’s feeling that he or she writes more code. Often, programmers assume that the project is slower because of automated testing.<\/p>\n\n\n\n How do I start? <\/i><\/b><\/p>\n\n\n\n The best way to adopt unit testing is carefully and incrementally, following a few important points:<\/p>\n\n\n\n Option 1<\/b>. <\/b>Clarify unit testing concepts<\/p>\n\n\n\n Programmers should handle fearlessly concepts like: stubs, mocks, state tests, collaboration tests, contract tests, dependency injection etc. Programmers should also understand what cases are worth testing.<\/p>\n\n\n\n Mastering this concept is possible in a few ways:<\/p>\n\n\n\n Option 2. <\/b>A technical coach or trainer can work with programmers, helping them transfer theoretical information in their everyday practice such that productivity is least affected<\/p>\n\n\n\n Option 3. <\/b>Write unit tests for the most important parts of the application and then of the features with the highest risk of mistake<\/p>\n\n\n\n Option 4. <\/b>Use the \u201cTest pyramid\u201d testing strategy to eliminate as many mistakes as possible<\/p>\n\n\n\n Option 5. <\/b>If lots of code without tests exists (legacy code), learning additional techniques to write tests on existing code is recommended. More details in a future article.<\/p>\n\n\n\n Common mistakes <\/i><\/b><\/p>\n\n\n\n A few common mistakes related to unit testing are:<\/p>\n\n\n\n Conclusion <\/i><\/b><\/p>\n\n\n\n Unit testing is one of the tools a programmer can use to significantly reduce the number of mistakes he or she makes when writing code. When correctly used, unit testing can significantly reduce the time spent with bug fixing, reducing the load on colleagues that take care of support and testing and allowing the introduction of new features faster, resulting in higher competitiveness.<\/p>\n\n\n\n\n
\n
\n
<\/a><\/pre>\n\n\n\n
<\/a>\n<\/pre>\n\n\n\n
<\/a><\/pre>\n\n\n\n
\n
\n
\n