Software Engineering — Lab 2

In this block we'll focus on testing (more precisely unit testing) and refactoring. In essance, unit testing is the art testing individual methods in isolation. Testing in a broader sense mostly refer to the art of verification. Remember to never hand in before all tests are passing. Be weary of false positives.

Seminar hand in

Write sufficient unit and integration tests for the Phone Book project you constructed in Block 1. Feel free to refactor your Phone Book solution if you find it difficult to test. Make sure your unit tests are fully isolated and that your integration tests are actually integrating. Strive for high code coverage.

Exercises

1.1 Introduction to testing

In this exercise we're going to familiarize ourselves with the concept of unit testing.

  1. Create a new Visual Studio Solution.
  2. Add a new Class Library project, and name it MathLibrary.
  3. Add a new Unit Test Project and name it MathLibraryTests
  4. Add the contents of the scaffold below.
  5. Create a new class in your MathLibraryTests project. Name it MathLibTests.
  6. Create a (or rename the default) class in your test project and name it MathLibTests.cs
  7. Add the contents of the scaffold below.
  8. Add a reference (via Solution Explorer) to the MathLibrary project in the MathLibraryTests project. We do this because the test project is going to test classes in the MathLibrary project, and thus need access to the classes.

MathLib contains a number of public static functions that perform math related operations. Not all methods are implemented. You must complete these implementations.

MathLibTests contains a number of unit tests that aim to verify the functionality of all public methods in the MathLib class. Not all tests are implemented. You must complete these implementations.

You decide whether you wish to write each test before each implementation or vice versa. Do not add or remove any methods. Make sure your handin contains both your implementation and your tests.

1.2 Refactoring

The purpose of this exercise is to practice the art of refactoring in controlled steps. Using tests to ensure correctnessa at each change. This exercise is designed by Martin Fowler, the author of the book Refactoring.

  1. Create a new Console Application and introduce the code of the following classes into your project.
  2. Introduce the following integration tests to your project. Run the integration tests. One should pass and one should fail. The one that fails is commented out. Ensure that the test does indeed fail if you remove the comments before moving further.
  3. Follow the instructions given in the following document step by step. Remember to run the integration tests between changes to ensure that you are not altering the behavior of the program.

Note that one of the integration tests is commented out. This test corresponds to the expected output of the functionality (i.e. the HTML statement) that the above document suggests you should be able to implement quite easily after refactoring. Make sure that also that test is passing before handing in.

2.3 Debugging via Tests

The purpose of this exercise is to use tests as a means of locating and fixing bugs. Matrix multiplication is not trivial. The person who built the class below thus failed. Your job is to use tests to locate and fix all bugs.

  1. Create a new Class Library project in Visual Studio.
  2. Download the class containing bugs, and add the code to your project.
  3. Create a Test Project in the same Solution.
  4. Create and run tests one by one in order to locate any bugs. Test all public methods.
  5. Fix the bugs either when you've written all tests or when you've encountered them.

2.4 Testing To Drive Design

Wikipedia on Test Driven Development

The purpose of this exercise is to explore the concept of letting tests drive implementation design. Your task is to implement a solution to the classic FizzBuzz problem. You are expected to employ test driven development and thus let your tests guide your implementation design.

The specification for the FizzBuzz problem is as follows.

  1. Any number divisible by 3 is a "Fizz".
  2. Any number divisible by 5 is a "Buzz".
  3. Any number divisible by 3 and 5 is a "FizzBuzz".
  4. Any number neither divisible by 3 nor 5 simply remain itself.
  5. Your implementation of FizzBuzz must somehow allow easy "counting".
    "1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz"

Make sure your handin contains both your implementation and your tests.