KS41CP2 6.1 28 min read 10 question quiz 15 exam marks

Developing and Testing Programs

Subprograms, readable and maintainable code, validation and authentication, the three kinds of error, and how to build a test plan that finds faults before an examiner does.

Subprograms

A subprogram is a named block of code that can be called from elsewhere. Python has one keyword for both kinds.

A procedure carries out a task and returns nothing:

Python
def greet(name):
    print("Hello", name)

greet("Amira")

A function returns a value:

Python
def area(width, height):
    return width * height

size = area(4, 7)

Parameters are the names in the definition, width and height. Arguments are the values passed in, 4 and 7. Parameters are what make a subprogram reusable: one that always calculates the area of a four by seven rectangle is useless.

Scope

A variable created inside a subprogram is local: it exists only while that subprogram runs, and it cannot be seen from outside.

Python
def tally():
    count = 0
    count = count + 1
    return count

This returns 1 every time it is called, because count is created fresh on each call. Local variables are the right default: two subprograms can each use a variable called i without interfering, and each subprogram can be tested on its own.

Why decomposition into subprograms matters

  • Code written once is called wherever it is needed, so there is no repetition.
  • A change is made in one place rather than in every copy.
  • Each subprogram can be tested on its own before it is trusted.
  • The main program reads as a list of named steps, which is far easier to follow.
A function takes values in and hands a value backA function drawn as a machine. The code defines area with two parameters, w and h, and returns w times h. The line x equals area of 3, 4 calls it: the two arguments, 3 and 4, drop into the machine through the hopper, and the result, 12, comes out of the chute and is stored in x, so print of x shows 12. Parameters are the names the function uses for what it is given, and arguments are the actual values supplied when it is called. Below, a procedure and a function are compared: a procedure does a job, such as printing a greeting, and gives nothing back, while a function hands a value back to the caller with return.area.py1def area(w, h):2    return w * h34x = area(3, 4)5print(x)output12A function is a machinearea(w, h)34arguments in12returnedw and h:parametersProceduredef hello():    print("Hi")does a job, givesnothing backFunctiondef double(n):    return n * 2hands a value backwith return1234
  1. Define it once with def, naming the parameters it will be given.
  2. Call it with arguments. They fill the parameters, w = 3 and h = 4.
  3. return hands the result back to the line that called it.
  4. A procedure does a job. A function also gives a value back.
Parameters are the names in the definition. Arguments are the values in the call.

Readable and maintainable code

Edexcel awards marks for code quality, not only for code that works.

Meaningful identifiers. total_price rather than tp or x2. The next reader, including you in a month, should not have to trace the program to work out what a variable holds.

Comments that explain why. count = count + 1 does not need a comment saying it adds one. It may need one saying why the first record is skipped.

Consistent indentation and blank lines separating logical sections, so the structure of the program is visible on the page.

Constants for fixed values. VAT_RATE = 0.2 at the top, used by name, changed in one place.

Subprograms so each task has one home and one name.

Write the comments as you go

Adding them at the end, under time pressure, produces the comments that restate the code and earn nothing. Written as you go they explain the decision you were actually making.

Validation, authentication and testing

Validation

Validation checks that entered data is reasonable. It cannot check it is true.

CheckTestsExample
RangeValue lies between limitsif 0 <= mark <= 100:
PresenceSomething was enteredif name != "":
LengthCorrect number of charactersif len(password) >= 8:
TypeData is of the expected typeif entry.isdigit():
FormatMatches a required patternif "@" in email:
Look upValue is one of a known setif county in COUNTIES:

A validation loop is the standard pattern and is worth memorising:

Python
mark = -1
while mark < 0 or mark > 100:
    entry = input("Enter a mark between 0 and 100: ")
    if entry.isdigit():
        mark = int(entry)
    else:
        print("Please enter a whole number.")

Authentication

Authentication checks the user is who they claim to be, usually with a username and password, strengthened by minimum length, mixed character types and a limit on failed attempts.

Validation asks "is that a sensible thing to type". Authentication asks "who are you". They are different jobs.

The three kinds of error

Syntax error. Breaks the rules of Python, such as a missing colon or bracket. The program will not run and the error is reported with a line number.

Logic error. The program runs and gives the wrong answer. Using + where - was meant, or < where <= was meant. Nothing reports it, which is why these are the expensive ones.

Runtime error. The program starts and then stops: dividing by zero, an index out of range, opening a file that does not exist.

Test data

TypeMeaningFor a mark from 0 to 100
NormalTypical accepted data55
BoundaryAt the edge of what is allowed, on both sides0, 100, and -1, 101
ErroneousShould be rejected"cat", blank, 3.5
Boundary data is where the bugs are

Almost every off by one error appears at a boundary and nowhere else. A program tested only with 55 will happily reject 0 and accept 101.

Trace table trainer

Fill in a trace table row by row and have it marked as you type. This tool needs JavaScript, so turn it on to use it. Everything you need to answer the exam question is explained in the text above.

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.
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

Subprogram
A named block of code that can be called from elsewhere in a program.
Procedure
A subprogram that carries out a task without returning a value.
Function
A subprogram that returns a value to the code that called it.
Parameter
A name in a subprogram definition that receives a value when it is called.
Argument
The actual value passed to a subprogram when it is called.
Local variable
A variable created inside a subprogram, existing only while it runs.
Validation
An automatic check that entered data is reasonable and of the expected form.
Authentication
Checking that a user is who they claim to be.
Syntax error
An error breaking the rules of the language, preventing the program from running.
Logic error
An error in which the program runs but produces the wrong result.
Runtime error
An error occurring while the program is running, causing it to stop.
Boundary test data
Data at the very edge of the acceptable range, on both sides of each limit.

Flashcards

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

DefineSubprogram
AnswerA named block of code that can be called from elsewhere in a program.
DefineProcedure
AnswerA subprogram that carries out a task without returning a value.
DefineFunction
AnswerA subprogram that returns a value to the code that called it.
DefineParameter
AnswerA name in a subprogram definition that receives a value when it is called.
DefineArgument
AnswerThe actual value passed to a subprogram when it is called.
DefineLocal variable
AnswerA variable created inside a subprogram, existing only while it runs.
DefineValidation
AnswerAn automatic check that entered data is reasonable and of the expected form.
DefineAuthentication
AnswerChecking that a user is who they claim to be.

Reach the top grade on this topic

Paper 2 gives marks for a program that works and for a program that is readable, and the second is far easier to secure than most candidates realise.

Decompose before you type. Three named subprograms and a short main section will always score better than one long block, and it is quicker to debug.

Validate every input the task mentions. Use the while loop pattern, and say in a comment which check you are applying.

Choose test data with a reason. "0 and 100 because they are the boundaries, and -1 and 101 because an incorrect comparison operator would only show up there" is the answer a mark scheme wants.

Be exact about the three errors. Will not run at all is syntax. Runs and gives the wrong answer is logic. Starts and then stops is runtime.

Mistakes that cost marks here

Avoid these
  • Saying validation checks that data is correct. It checks that data is reasonable.
  • Giving only one boundary value. A boundary needs testing on both sides.
  • Calling a crash a logic error. A program that stops while running has a runtime error.
  • Writing comments that restate the code rather than explaining the decision.
  • Initialising a counter inside the subprogram that is supposed to increase it, so it resets on every call.
Fun fact

The cost of fixing a fault rises sharply the later it is found. A mistake caught while writing a function costs minutes. The same mistake caught after release can cost thousands of times more, which is the whole reason testing exists.

Knowledge check

0 of 10 answered
1What is the difference between a procedure and a function?
2In def area(width, height), what are width and height?
3A program will not run and Python reports a missing colon. What kind of error is this?
4A program runs but calculates an average by dividing by the wrong number. What kind of error is this?
5For a value that must be between 1 and 20, which set is boundary test data?
6What can validation never do?
7Why does a subprogram that initialises its counter internally return the same value every call?
8Which is the best example of a useful comment?
9A program stops with an error when it tries to open a file that has been deleted. What kind of error is this?
10What is erroneous test data used to check?
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.

15 marks
1State one advantage of using subprograms in a long program.2 marks
State

Mark scheme0 / 2
  • LCode written once can be called from many places, reducing repetition
  • LOr each subprogram can be tested and maintained on its own
Model answer

A task written once as a subprogram can be called from every point that needs it, which removes repeated code, and because that task lives in one named place a correction only has to be made once rather than in every copy.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
2Write a Python validation loop that repeatedly asks the user for a whole number between 1 and 10 until a valid value is entered.4 marks
Write

Mark scheme0 / 4
  • LUses a while loop that repeats until the value is acceptable
  • LChecks that the entry is a whole number
  • LChecks that the value is within the range 1 to 10
  • LGives the user a message when the entry is rejected
Model answer

A correct answer is: number = 0, then while number < 1 or number > 10:, then entry = input("Enter a number from 1 to 10: "), then if entry.isdigit(): number = int(entry), then if number < 1 or number > 10: print("That is outside the range."), else: print("Please enter a whole number."). The loop condition must be false only for acceptable values, the entry must be checked for being numeric before int() is applied so that typing a word does not crash the program, and a message tells the user what was wrong rather than simply asking again.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
3Explain the difference between validation and authentication.3 marks
Explain

Mark scheme0 / 3
  • LValidation checks that data entered is reasonable or of the expected form
  • LAuthentication checks that a user is who they claim to be
  • LGives an example of each, such as a range check and a password
Model answer

Validation is a check on the data itself, confirming that what has been entered is reasonable and of the form expected, for example that a mark lies between 0 and 100 or that a required field is not blank. It says nothing at all about who typed it. Authentication is a check on the person, confirming that the user is who they claim to be, usually through a username and password or a biometric check. The two are separate jobs: a system with perfect validation still has no idea who is using it, and a system with strong authentication will still accept a nonsensical value if it does not validate.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
4Describe the three types of error a programmer may encounter, giving an example of each.6 marks
Describe

Mark scheme0 / 6
  • LA syntax error breaks the rules of the language
  • LGives an example such as a missing colon or bracket, and notes the program will not run
  • LA logic error means the program runs but gives the wrong result
  • LGives an example such as using the wrong operator, and notes nothing reports it
  • LA runtime error occurs while the program is executing and stops it
  • LGives an example such as dividing by zero or an index out of range
Model answer

A syntax error breaks the rules of the programming language, for example a missing colon at the end of an if statement or an unclosed bracket. Python cannot interpret the line, so the program does not run at all and the error is reported with a line number, which makes it the easiest kind to fix. A logic error is different in kind: the code is valid, so the program runs from start to finish, but the instructions do not do what the programmer intended, so the output is wrong. Using a plus where a minus was meant, or less than where less than or equal to was meant, produces a logic error, and nothing reports it, which means it can only be found by testing with data whose correct answer is already known or by tracing the program by hand. A runtime error occurs while the program is executing and causes it to stop, for example dividing by zero, reading past the end of a list, or trying to open a file that does not exist. The program was valid and started normally, so a runtime error usually reflects data the programmer did not anticipate rather than a mistake in the code's structure, which is why validation and error handling reduce them.

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