Writing test cases before the code

Tip: Choose Save as PDF in the print dialog to download. Use A4 paper size.

Writing test cases before the code

Name:
Date:
Class:

Quick Questions

Shade in the A or B circle for each question.

1. When is the best time to write your test cases and expected results?
A After the code works, using what it prints
B Before you write the code, using the requirements
2. Requirement: 'Students aged 13 to 18 can join.' Which test case could you write before any code exists?
A Input 12, expected output: rejected
B Input 12, expected output: whatever the program prints
3. Which is the better source for an expected result?
A The requirements
B The program's actual output
4. A student writes the code first, runs it, then records the output as the 'expected' result. What is the problem?
A There is no problem because the tests will always pass
B The test only checks what the code does, so bugs can pass
5. Requirement: 'Give 10% off orders of $100 or more.' Which expected result is written correctly from the requirement?
A Input 100, expected output 90
B Input 100, expected output 100 because the code uses > 100

Match the Pairs

Draw a line connecting each item on the left to its match on the right.

Left columnRight column
1assert grade(50) == "Pass" ATests were left until after the code was written, so they are likely to be shaped around the code instead of the requirements.
2tests = [(49, "Fail"), (50, "Pass")] BThe expected result was taken from the code's own output, so the test only confirms what the code does, even if it is wrong.
3Write the expected output from the requirement, not from what your code prints CA list of inputs and expected results written first, to be rerun each time the code grows
4Rerun every test as the code grows to catch anything a new change breaks Dexpected = 100 - 100 * 0.1 # 10% discount rule
5expected = total(5) # copied from my code's output Efor inp, exp in tests: print(f(inp) == exp)
6def grade(m): ... # write code, then think of tests later FA test written from the requirement '50 or more is a Pass', ready before grade() exists

Definitions

test first

Fill in the Blanks

Complete each line of code by filling in the missing parts.

1.
# Req: pass mark is 50 or more ______ passed(50) == True
2.
# Req: 49 fails assert passed(49) __ False
3.
# Req: 50 or more passes assert ______(50) == True
4.
# Req: 50 or more passes ___ passed(mark): return mark >= 50
5.
tests = [(50, True), (49, False)] for mark, expected in _____: print(passed(mark) == expected)

Spot the Error

Shade in the letter of the line that contains an error.

Question 1
A # Rule: 10% off from 100 up
B assert price(50) == 50
C assert price(200) == 200
D assert price(100) == 90
Question 2
A # Rule: allowed if age >= 13
B tests = [(12, False),
C (13, False),
D (30, True)]
Question 3
A tests = [(49, 'F'), (50, 'P')]
B for mark, want in tests:
C if grade(mark) == mark:
D print('PASS')
E else:
F print('FAIL')
Question 4
A expected = 4 + 5 # area
B actual = area(4, 5)
C print('Expected', expected)
D print('Actual', actual)
Question 5
A def run_tests():
B assert total([2, 3]) == 5
C assert total([]) == 0
D run_test()
E print('Tests passed')

Answer Key

Writing test cases before the code
Section A: Quick Questions
Q1
B — Before you write the code, using the requirements
Q2
A — Input 12, expected output: rejected
Q3
A — The requirements
Q4
B — The test only checks what the code does, so bugs can pass
Q5
A — Input 100, expected output 90
Section B: Match the Pairs
Q1
assert grade(50) == "Pass" → A test written from the requirement '50 or more is a Pass', ready before grade() exists
Q2
tests = [(49, "Fail"), (50, "Pass")] → A list of inputs and expected results written first, to be rerun each time the code grows
Q3
Write the expected output from the requirement, not from what your code prints → expected = 100 - 100 * 0.1 # 10% discount rule
Q4
Rerun every test as the code grows to catch anything a new change breaks → for inp, exp in tests: print(f(inp) == exp)
Q5
expected = total(5) # copied from my code's output → The expected result was taken from the code's own output, so the test only confirms what the code does, even if it is wrong.
Q6
def grade(m): ... # write code, then think of tests later → Tests were left until after the code was written, so they are likely to be shaped around the code instead of the requirements.
Section C: Definitions
Q1
test first — Write test cases and expected results from the requirements before coding, so they check what the program should do, not what your code does. Rerun them as it grows.
Section D: Fill in the Blanks
Q1
# Req: pass mark is 50 or more assert passed(50) == True
Q2
# Req: 49 fails assert passed(49) == False
Q3
# Req: 50 or more passes assert passed(50) == True
Q4
# Req: 50 or more passes def passed(mark): return mark >= 50
Q5
tests = [(50, True), (49, False)] for mark, expected in tests: print(passed(mark) == expected)
Section E: Spot the Error
Q1
C — The expected value must come from the requirement. A 10% discount on 200 gives 180, not 200. The test should read assert price(200) == 180.
Q2
C — The rule says age 13 or over is allowed, so the boundary value 13 must expect True. The test should be (13, True).
Q3
C — The result must be compared with the expected value want, which was written from the requirements. Comparing it with the input mark makes the test meaningless. It should be if grade(mark) == want:.
Q4
A — The requirement says area is width times height, so the expected result for 4 and 5 is 20. Adding gives 9, which is wrong. It should be expected = 4 * 5.
Q5
D — The function is called run_tests, so run_test() causes a NameError and the tests never run. The tests need to run every time the code grows. It should be run_tests().