University of London CM 2010 Software Design and Development
Three laws of unit-testing:
The following special issue on test-driven development contains several interesting articles:
(PDF) Segura, S. and Z.Q. Zhou ‘Metamorphic testing 20 years later: a hands-on introduction’, 2018 IEEE/ACM 40th International Conference on Software Engineering: Companion (ICSE-Companion) 2018, pp.538–539.
(PDF) Borle, N., M. Feghhi, E. Stroulia, R. Grenier and A. Hindle ‘[Journal First] Analyzing the effects of test driven development in GitHub’, 2018 IEEE/ACM 40th International Conference on Software Engineering (ICSE) 2018, pp.1062–1062.
Requirement
Test: does the getHighest
function return a value?
Write a failed test.
function testReturnVal() {
let input = [1, 2, 4, 5, 6];
let result = getHighest(input);
return !(result == undefined);
}
let result1 = testReturnVal();
if (result1) console.log("testReturnVal passed");
else console.log("testReturnVal failed");
// ReferenceError: getHighest is not defined
Write the minimum code to pass the test.
function getHighest(input) {
return 0;
}
// testReturnVal passed
Test: does it return a value from the array?
function testResultInArray() {
let input = [1, 2, 3];
let result = getHighest(input);
return result == 1 || result == 2 || result == 3;
}
let result2 = testResultInArray();
if (result2) console.log("testResultInArray passed");
else console.log("testResultInArray failed");
// testReturnVal passed
// testResultInArray failed
Change getHighest()
to:
function getHighest(input) {
return input[0];
}
// testReturnVal passed
// testResultInArray passed
Test: does it return the correct array/value?
function testCorrectResult() {
let input = [1, 2, 3];
let result = getHighest(input);
return result == 3;
}
...
let result3 = testCorrectResult();
if (result3) console.log("testCorrectResult passed");
else console.log("testCorrectResult failed");
// testReturnVal passed
// testResultInArray passed
// testCorrectResult failed
Change getHighest()
to:
function getHighest(input) {
let max = input[0];
for (let i = 0; i < input.length; i++) {
if (input[i] > max) max = input[i];
}
return max;
}
// testReturnVal passed
// testResultInArray passed
// testCorrectResult passed
interface testing: test if a function receives the correct input(s) and output(s), not user interface.
exercising data structure: verifying data structures’ been used correctly and being stored.
boundary testing: specifying boundaries in software.
i.e. a function takes an integer as input, what if I put in 0? what’s the highest value I can put in?
i.e. a function finds certain things in an array, can it find the first/last element correctly?
execution paths: tests deliberately go through all paths available in a given module.
error handling: is the error descriptive/intelligible? does the error match what actually happened? does itt reach the error handling code (i.e. crash before reach)?
import unittest
class TestSetForOneModule(unittest.TestCase):
def test_arithmetic_pass(self):
self.assertEqual(2+2, 4)
def test_arithmetic_fail(self):
self.assertEqual(2+2, 3)
unittest.main(argv=['ignored', '-v'], exit=False)
This week we will be working with various tools. You can use our browser-based JavaScript environment to carry out the work – in that case, you should not need to install anything.
If you plan to work on your own machine, you will be given instructions on which tools to install later, but you can get start now by installing Node.js. We recommend version 12 LTS.
We will be using Mocha and Chai to carry out the unit testing.
Might need
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
for PowerShell to run the tests.