KS4J277 2.3 30 min read 10 question quiz 21 exam marks

Producing Robust Programs

Defensive design, validation, authentication, maintainability, and how to design a test plan that actually finds the bugs rather than confirming what you already believe.

Defensive design

Defensive design means writing a program that continues to work correctly even when things go wrong: bad input, unexpected use, or a missing file.

Anticipating misuse

Ask what a user might do that you did not intend:

  • Typing letters where a number is expected
  • Entering a date of birth in the future
  • Leaving a field blank
  • Entering an enormous number
  • Pressing buttons in an unexpected order
  • Entering SQL or script code into a text field

Input validation

Validation checks that input is sensible and in the expected format before the program uses it.

CheckWhat it doesExample
Range checkValue falls between limitsAge between 0 and 120
Type checkData is the expected typeAge is a whole number
Presence checkSomething has been enteredSurname is not blank
Length checkRight number of charactersPassword at least 8 characters
Format checkMatches a required patternEmail contains an at sign
Look up checkValue is one of a permitted listYear group is 7, 8, 9, 10 or 11
Python
age = input("Enter your age: ")

while not age.isdigit() or int(age) < 0 or int(age) > 120:
    print("Please enter a whole number between 0 and 120.")
    age = input("Enter your age: ")

age = int(age)

This performs a type check and a range check, and loops until the input is acceptable rather than crashing.

Validation is not verification

Validation checks that data is sensible. Verification checks that it was entered correctly, for example by asking for a password twice or by asking the user to confirm. A date of birth of 01/01/1900 is valid but may not be correct.

Authentication

Authentication confirms the user is who they claim to be.

  • Usernames and passwords
  • Two factor authentication, where a code is sent to a separate device
  • Biometrics such as fingerprint or face recognition
  • Security questions

Passwords should be stored hashed, not in plain text, so a stolen database does not reveal them.

Maintainability

Code that is easy to understand and change later.

  • Meaningful identifiers. totalPrice not tp
  • Comments explaining why something is done, not restating what the line obviously does
  • Indentation showing structure clearly
  • Subroutines so each task is separated
  • Constants instead of unexplained numbers scattered through the code
  • White space grouping related lines
Why maintainability matters

Programs are read far more often than they are written, and are usually maintained by someone other than the original author. Code that cannot be understood cannot safely be changed.

Validation checks, and what they cannot doSix validation checks, one card each, with a value that is rejected and a value that is accepted. A presence check makes sure something is entered, so an empty entry is rejected. A type check makes sure the data is the right kind, so the letters abc are rejected for an age. A range check keeps a number between limits, so an age of 200 is rejected. A length check makes sure there are enough characters, so pass is too short for a password of eight or more. A format check makes sure the data matches a pattern, so asha dot com is not an email address without an at sign. A lookup check makes sure the value is one of an allowed list, so Funday is not a day of the week. Two cards underneath separate validation from correctness: validation checks data is sensible, not that it is true, so an age of 15 mistyped as 51 passes a range check and is still wrong. Verification checks that data was entered as intended, for example by typing a password twice and comparing.Presencesomething must be entered""AshaTypethe right kind of data"abc"15Rangebetween two limits (0 to 120)20015Lengthenough characters (8 or more)"pass""pass1234"Formatmatches a pattern"asha.com""asha@mail.com"Lookupone of an allowed list"Funday""Friday"1Valid is not the same as trueAge 15 mistyped as 51 is in range,so every check passes and thedata is still wrong.validation checks it is sensible, not that it is trueVerification: typed twicepasswordenter itconfirmand enter it againdo they match?23
  1. Validation checks: presence, type, range, length, format and lookup.
  2. Validation checks that data is sensible. It cannot know whether it is true.
  3. Verification asks the user again, for example with a confirm password box, to catch typing slips.
Validate on the way in, and tell the user what is wrong, not just that something is.
Authentication: what you know, have and are, and how passwords are keptAuthentication proves who someone is, using three kinds of evidence, one card each: something you know, such as a password or PIN; something you have, such as a phone showing a one time code, a bank card or a key fob; and something you are, such as a fingerprint or a face. Using two of them together, two factor authentication, is far stronger than one. The login flow shows it: the user enters a username and password, a code is sent to their phone, and only then is access granted, so a stolen password alone is not enough. Underneath, a password should never be stored as typed. The system keeps only a hash, the output of a one way function, so password123 is stored as a string of characters such as 5f4dcc3b and the real password is never kept. If the file is stolen, it does not reveal the passwords.Something you know• • • • • • • •password, PINSomething you have482 913codephone, bank card, key fobSomething you arefingerprint, face1Two-factor loginusername +passwordcode sent toyour phoneaccessgranteda stolen password alone is not enoughthe second factor is something an attacker does not have2Stored as a hashpassword123hash function5f4dcc3b5aa765d6...the real password is never kept,so a leak does not reveal it3
  1. Three kinds of evidence: something you know, have or are.
  2. Two factors together are far stronger than one: a stolen password alone is not enough.
  3. Passwords should be stored as hashes, never as typed, so a leak does not reveal them.
Strong authentication is layers. No single one of them is enough alone.

Testing

The two kinds of testing

Iterative testing happens during development. Each part is tested as it is written, and corrected before moving on. Problems are found early, when they are cheap to fix.

Final testing, sometimes called terminal testing, happens when development is complete. The whole program is tested against the original requirements to confirm it does everything it was supposed to.

The three kinds of error

ErrorWhat it isExample
Syntax errorThe code breaks the rules of the language, so it will not run at allMissing colon, misspelled keyword, unclosed bracket
Logic errorThe program runs, but produces the wrong resultUsing + where * was intended, or > where >= was needed
Runtime errorThe program crashes while runningDividing by zero, opening a file that does not exist
Syntax errors are the easy ones

The computer finds them for you. Logic errors are dangerous precisely because the program runs perfectly and quietly gives the wrong answer.

Test data

You must be able to choose test data of each type and say what it proves.

TypeMeaningExample for ages 11 to 18
NormalTypical values that should be accepted14
BoundaryValues at the very edge of what is allowed11 and 18, and also 10 and 19
Invalid or erroneousValues of the right type but outside the allowed range25
ErroneousValues of the wrong type entirely"fourteen", or a blank entry

Boundary data is the most valuable, because it is exactly where the off by one errors live. If the check should be >= 11 but was written > 11, only a test with the value 11 will reveal it.

Writing a test plan

A test plan is a table:

TestTest dataTypeExpected resultActual result
114NormalAcceptedAccepted
211BoundaryAcceptedAccepted
310BoundaryRejected with a messageRejected
425InvalidRejected with a messageRejected
5"abc"ErroneousRejected with a messageProgram crashed

The last row is the point of testing. Test 5 has found a real fault.

Always state the expected result

A test with no expected result proves nothing, because you have no standard to compare against. This is worth a mark in test plan questions.

The three kinds of error: syntax, runtime and logicThe three kinds of programming error, one card each, each with its own bug. A syntax error breaks the rules of the language, like print with an opening bracket that is never closed. The translator cannot understand the line, reports a SyntaxError and the program will not start. A runtime error happens while the program is running: dividing 10 by 0 makes the program start and then crash on that line with a ZeroDivisionError. A logic error is the hardest to find because nothing crashes: the program average equals a plus b divided by 2 runs happily and prints 8.0, when the average of 4 and 8 is 6.0, because division is done before addition. Only testing against the answer you expected finds it.Syntax errora typo in the rules of the languageprint("Hello"resultSyntaxError:'(' was never closedfound how?found before it runs,by the translatorRuntime errorthe program starts, then crashesx = 10 / 0resultZeroDivisionError:division by zerofound how?found while it runs:it stops on that lineLogic errorruns fine, gives a wrong answera, b = 4, 8average = a + b / 2print(average)result8.0(should be 6.0)found how?found only by testing againstthe answer you expected123
  1. Syntax error: the code breaks the rules of the language, so it will not run at all.
  2. Runtime error: the program starts, then crashes when it meets something it cannot do.
  3. Logic error: it runs without complaint but gives the wrong answer, so only testing finds it.
A program that runs is not a program that is right. Test the answers, not only the absence of crashes.
Normal, boundary and erroneous test dataTest data for a program that asks for an age from 13 to 19. A number line shows the valid range in green, from 13 to 19, and the invalid values in red either side. Normal data is a typical value inside the range, such as 16. Boundary data sits on the edge of what is allowed and just outside it: 13 and 19 are the two valid boundaries and 12 and 20 are the first invalid values either side. Erroneous data is the wrong type or not sensible at all, such as the text abc, a negative number or an empty entry. Beneath, a test plan lists each test with its data, type, expected result and actual result. The first three pass. The fourth, the text abc, was expected to make the program ask again but the program crashed, so it fails, and that points to a missing validation check.Test data for: enter an age from 13 to 1901213161920invalidvalidinvalidnormal: 16boundary: 12, 13boundary: 19, 20erroneous:"abc"-5emptythe wrong type, or not a sensible value123A test plan, with the result of each testTestDataTypeExpectedActualPass?116normalacceptedaccepted213boundaryacceptedaccepted312boundaryrejectedrejected4"abc"erroneousasks againcrashes4
  1. Test data for an age from 13 to 19, on a number line.
  2. Normal data is typical and should be accepted.
  3. Boundary data sits on and just outside each edge, because that is where mistakes hide.
  4. A test plan records expected against actual. A failed test shows what to fix.
Always test at the boundaries, on both sides of each one.

Key terms you must be able to define

Defensive design
Designing a program to keep working correctly even when it is given unexpected input or used incorrectly.
Validation
Checking that input data is sensible and in the expected format before it is used.
Range check
A validation check that a value falls between an upper and a lower limit.
Presence check
A validation check that data has actually been entered.
Format check
A validation check that data matches a required pattern.
Authentication
Confirming that a user is who they claim to be.
Maintainability
How easily a program can be understood and changed by another programmer later.
Iterative testing
Testing carried out during development, as each part is written.
Final testing
Testing the complete program against its original requirements once development is finished.
Syntax error
An error that breaks the rules of the programming language so the program will not run.
Logic error
An error where the program runs but produces an incorrect result.
Boundary data
Test data at the very edge of the acceptable range, where errors are most likely.
Erroneous data
Test data of the wrong type entirely, which should be rejected.

Flashcards

Say the definition out loud before you flip the card. Retrieving it from memory is what builds recall, reading it again is not.

DefineDefensive design
AnswerDesigning a program to keep working correctly even when it is given unexpected input or used incorrectly.
DefineValidation
AnswerChecking that input data is sensible and in the expected format before it is used.
DefineRange check
AnswerA validation check that a value falls between an upper and a lower limit.
DefinePresence check
AnswerA validation check that data has actually been entered.
DefineFormat check
AnswerA validation check that data matches a required pattern.
DefineAuthentication
AnswerConfirming that a user is who they claim to be.
DefineMaintainability
AnswerHow easily a program can be understood and changed by another programmer later.
DefineIterative testing
AnswerTesting carried out during development, as each part is written.

Reach the top grade on this topic

Two things reliably separate the top answers.

Name the specific validation check. Not "check the input is right", but "a range check to confirm the age is between 11 and 18, and a type check to confirm a whole number has been entered".

Choose boundary data that is actually on the boundary. For a range of 11 to 18, the boundary values are 10, 11, 18 and 19. Testing 5 and 30 proves far less, because they are nowhere near the point where the logic changes.

Give every test an expected result. A test plan without expected results scores badly, because there is nothing to compare the actual result against.

Be precise about error types. A syntax error stops the program running at all. A logic error lets it run and produce the wrong answer. Students frequently give a logic error as an example of a syntax error.

  • Design a five row test plan with normal, boundary and erroneous data and expected results
  • Write a validation loop that rejects both wrong types and out of range values
  • Explain three ways to make a program maintainable, each with a reason
  • Classify any given error correctly as syntax, logic or runtime

Mistakes that cost marks here

Avoid these
  • Giving a logic error as an example of a syntax error. A missing colon is syntax, using plus instead of times is logic.
  • Choosing boundary data that is not on the boundary.
  • Writing a test plan with no expected results.
  • Saying validation checks data is 'correct'. It checks data is sensible. Verification checks it was entered correctly.
  • Listing 'use comments' as the only way to improve maintainability, without meaningful names, indentation and subroutines.
  • Describing authentication as validation. They are different: authentication confirms identity, validation checks data.
Fun fact

A robust program assumes the user will do the worst possible thing at the worst possible moment. This is not pessimism, it is professionalism. The most expensive bugs in history were all inputs that nobody thought anyone would ever enter.

Knowledge check

0 of 10 answered
1Which validation check would ensure a password is at least 8 characters?
2A program runs but calculates the average incorrectly. This is:
3For a field accepting values 1 to 10, which is boundary test data?
4What is the difference between validation and verification?
5Which is an example of a syntax error in Python?
6Why is boundary test data particularly valuable?
7Which of these improves the maintainability of a program?
8What is iterative testing?
9A program asks for a year group and accepts 7, 8, 9, 10 or 11. Which validation check is most appropriate?
10Passwords should be stored in a hashed form so that:
Score 0 / 10

Exam-style questions

Five written questions in the style of the real paper. Write a full answer, then let the marker check it against the mark scheme.

21 marks
1State two validation checks that could be applied to a field where a user enters their email address.2 marks
State

Mark scheme0 / 2
  • LA presence check to ensure something has been entered
  • LA format check to ensure it contains an at sign and a domain
Model answer

A presence check could be used to ensure that the field has not been left blank. A format check could also be applied, confirming that the entry contains an at sign followed by a domain name with a full stop, since an email address without those parts cannot be valid.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
2Explain the difference between a syntax error and a logic error, giving an example of each.4 marks
Explain

Mark scheme0 / 4
  • LA syntax error breaks the rules of the programming language
  • LThe program will not run at all until it is corrected
  • LA logic error means the program runs but produces an incorrect result
  • LGives valid examples of each, such as a missing colon and using the wrong operator
Model answer

A syntax error occurs when the code breaks the rules of the programming language, for example a missing colon at the end of an if statement or an unclosed bracket. Because the code is not valid, the program will not run at all until the error is corrected, and the development environment will usually point to the offending line. A logic error is different: the code is completely valid and the program runs without complaint, but the instructions do not do what the programmer intended, so the output is wrong. An example would be writing total = total - price instead of total = total + price when calculating a shopping basket, or using a greater than sign where greater than or equal to was needed. Logic errors are more dangerous because nothing alerts the programmer to them, and they can only be found through careful testing.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
3A program accepts a temperature reading between -50 and 50 degrees. Design a test plan containing four tests, stating the test data, the type of data and the expected result for each.6 marks
Design

Mark scheme0 / 6
  • LIncludes normal data within the range
  • LIncludes boundary data at the edge of the accepted range
  • LIncludes boundary data just outside the accepted range
  • LIncludes erroneous data of the wrong type
  • LStates the type of each piece of test data
  • LStates an expected result for every test
Model answer

Test 1 uses the value 20, which is normal data well within the accepted range, and the expected result is that the value is accepted and processed. Test 2 uses the value 50, which is boundary data at the very top of the accepted range, and the expected result is that it is accepted, since the range is inclusive. Test 3 uses the value 51, which is boundary data just outside the accepted range, and the expected result is that it is rejected with an error message asking the user to try again. Test 4 uses the entry "hot", which is erroneous data of the wrong type entirely, and the expected result is that the program rejects it with an error message rather than crashing. A fifth useful test would be -51, checking the lower boundary from the outside, since an error at one end of a range does not guarantee an error at the other.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
4Explain three ways in which a programmer can make their code more maintainable.6 marks
Explain

Mark scheme0 / 6
  • LUse meaningful variable and subroutine names
  • LSo that another programmer can understand the purpose without tracing the logic
  • LUse comments to explain sections of code
  • LUse consistent indentation to show the structure
  • LUse subroutines so each task is separated and can be located easily
  • LUse constants rather than unexplained numbers appearing throughout the code
Model answer

The first way is to use meaningful identifiers. Naming a variable totalPriceIncludingVat rather than t means another programmer can understand what the value holds immediately, without tracing back through the code to work it out, and the same applies to subroutine names that describe the task they perform. The second way is to use comments and consistent indentation. Comments should explain why something is being done, particularly where the reason is not obvious, rather than restating what the line clearly does, and consistent indentation makes the structure of loops and selection statements visible at a glance so the flow of the program can be followed quickly. The third way is to break the program into subroutines and use named constants. Separating each task into its own subroutine means a programmer looking for a particular piece of behaviour knows exactly where to find it and can change it without risk to the rest of the program, and replacing values such as 0.2 with a named constant like VAT_RATE means the value appears once, is self explanatory, and can be updated in a single place if the rate ever changes.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
5Explain why a program that asks for a user's age should include input validation.3 marks
Explain

Mark scheme0 / 3
  • LUsers may enter data that is the wrong type or outside a sensible range
  • LWithout validation the program may crash or produce incorrect results
  • LValidation checks the input is sensible before it is used, allowing the program to ask again
Model answer

Input validation is needed because users cannot be relied upon to enter data in the expected form. Someone might type letters instead of digits, enter a negative age, leave the field blank, or enter an impossibly large number, whether by accident or deliberately. Without validation the program would attempt to use that input directly, which could cause it to crash when it tries to convert text into a number, or to continue running and produce meaningless results such as calculating a negative average. Validation checks the input against sensible criteria, such as a type check that a whole number has been entered and a range check that it falls between 0 and 120, and rejects anything that fails with a clear error message so the user can try again. This makes the program robust, meaning it keeps working correctly regardless of what the user does.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
Machine mark 0 / 21