Object-Oriented Programming/Unit Testing

This lesson introduces unit testing and test-driven development.

Objectives and Skills
Objectives and skills for this lesson include:

Readings

 * 1)  Software testing
 * 2)  Unit testing
 * 3)  Test-driven development
 * 4)  Code coverage

General

 * 1) YouTube: Unit Testing

C#

 * 1) YouTube: Test driven development (TDD) - Tutorial for Beginners

Java

 * 1) YouTube: Unit Test Coverage as in Eclipse; Technical Debt

JavaScript

 * 1) Youtube: Unit Tests, Integration Tests & e2e Tests in Javascript

Python

 * 1) YouTube: Writing Unit Tests in Python
 * 2) YouTube: 100% Test Coverage in Python

Examples

 * C#
 * /Java/
 * /JavaScript/
 * /Python3/

Activities

 * 1) Review  Unit testing. Using an appropriate testing library for your selected programming language, create a separate test class and add unit tests to test all aspects of the class. Run tests automatically when the class module itself is run as the main program.
 * 2) Run a code coverage report to verify that you are testing 100% of your BMI class.
 * 3) Update program, class, and method documentation, consistent with the documentation standards for your selected programming language.

Lesson Summary

 * Unit tests are short code fragments created by programmers or occasionally by white box testers during the development process.


 * The unit test usually should not go outside of its own class boundary. It especially should not cross process/network boundaries, because this can introduce unacceptable performance problems to the unit test suite.


 * The goal of unit testing is to isolate each part of the program and show that the individual parts are correct.


 * Code coverage allows the software team to examine parts of a system that are rarely tested and ensures that the most important function points have been tested.


 * Test-driven development (TDD) is a programming methodology in which unit tests are created before the code itself is written. When the tests pass, the code is considered complete. It relies on the repetition of a very short development cycle: requirements are turned into very specific test cases, and then the software is improved in order to pass the new tests.


 * TDD follows these steps: 1. Write the code, 2. Run tests, 3. Refactor code (restructuring existing computer code), 4. Repeat.


 * Software testing is a combinatorial problem. Every Boolean decision statement requires at least two tests: one with an outcome of "true" and one with an outcome of "false".


 * It is necessary to create relevant initial conditions. Otherwise, the test will not be exercising the code in a realistic context, which diminishes the value and accuracy of unit test results.


 * It is essential to keep careful records of the tests that have been performed and all changes that have been made to the source code of any unit in the software.


 * It is essential to implement a sustainable process for ensuring that test case failures are reviewed regularly and addressed immediately.


 * It is possible to perform unit testing without the support of a specific framework by writing client code that exercises the units under test and uses assertions, exception handling, or other controls flow mechanisms to signal failure.


 * Have an effective layout of a test case to ensure all required actions are completed. This will improve the readability of the test case, and smooths the flow of execution. Consistent structure helps in building a self-documenting test case. A commonly applied structure for test cases has the following: 1. Set up, 2. Execution, 3. Validation, 4. Cleanup.


 * Even though TDD requires more code writing, the total code implementation time could be shorter.


 * A benefit of TDD allows the programmer to eliminate defects early in the process, which avoids lengthy and tedious debugging later in the project.


 * The limitations of TDD is that it does not perform sufficient testing in situations where full functional tests are required to determine success or failure due to extensive use of unit tests. The unit tests created in a test-driven development environment are typically created by the developer who is writing the code being tested, which could lead to error.


 * Another concern is that a high number of passing unit tests may bring a false sense of security, resulting in fewer additional software testing activities, such as integration testing and compliance testing.


 * For code visibility, code has to be able to clearly access the code it is testing. However, normal design criteria such as information hiding, encapsulation, and the separation of concerns should not be compromised. Therefore, unit test code for TDD is usually written within the same project or module as the code being tested. In object-oriented design, this still does not provide access to private data and methods. Therefore, extra work may be necessary for unit tests.
 * When using TDD for complex systems, challenging systems requires a modular architecture, well-defined components with published interfaces, and disciplined system layering with maximization of platform independence. These proven practices yield increased testability and facilitate the application of build and test automation.

Key Terms

 * automation framework
 * An automated space outside of the calling context for which it was originally created. Testing in such an isolated manner reveals unnecessary dependencies between the code being tested and other units or data spaces in the program.


 * code coverage (test coverage)
 * A measurement used to describe the degree to which the source code of a program is executed when a particular test suite or set of unit tests runs.


 * extreme programming
 * A software development process that aims to test everything that could possibly break. In extreme programming, the developer writes a unit test that exposes either a software requirement or a defect. This test will then fail because either the requirement isn't implemented yet, or because it intentionally exposes a defect in the existing code. Then, the developer writes the simplest code to make the test, along with other tests, pass.


 * parameterized unit test (PUT)
 * Tests that take parameters. Unlike traditional unit tests, which are usually closed methods, PUTs take any set of parameters.


 * test case
 * A specification of the inputs, execution conditions, testing procedure, and expected results that define a single test to be executed to achieve a particular software testing objective.


 * test-driven development
 * A software development process that relies on the repetition of a very short development cycle. Requirements are turned into very specific test cases. Then the software is improved to pass the new tests.


 * test oracle
 * In computing, software engineering, and software testing, a test oracle, or just oracle, is a mechanism for determining whether a test has passed or failed.


 * unit
 * In object-oriented programming, a unit is often an entire interface, such as a class, but could be an individual method.


 * unit testing
 * Unit tests are typically written and run by software developers to ensure that code meets its design and behaves as intended.

General

 * Unit Testing

C#

 * Microsoft: Unit test basics

Java

 * Vogella: JUnit

JavaScript

 * Flavio Copes: Jest

Python

 * PythonTesting: Unittest Introduction
 * Tuts Plus: Write Professional Unit Tests in Python
 * Code Coverage: Coverage.py
 * How to Write Unit Tests for Python Functions