1 / 21

CMPT 125

CMPT 125. Verification and Testing. Objectives. Write pre-conditions and post-conditions for functions Write simple loop invariants for functions Use assert statements to check invariants Use assert statements to test methods. Beans in a Can Game. Rules.

linus-ware
Download Presentation

CMPT 125

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CMPT 125 Verification and Testing

  2. Objectives • Write pre-conditions and post-conditions for functions • Write simple loop invariants for functions • Use assert statements to check invariants • Use assert statements to test methods John Edgar

  3. Beans in a Can Game John Edgar

  4. Rules • A can contains black and white beans Two players take it in turns to remove two beans from the can • If the two beans are the same colour, put back a black bean • If the two beans are different colours put back a white bean • They continue until only one bean remains • The player who initially guesses the colour of the last remaining beans wins the games (and the beans?) • What should you guess if there are 51 white beans and 51 black beans in the can at the start? • Is there a general rule that tells you what colour to guess? John Edgar

  5. Writing Algorithms • Writing code, testing it and debugging it are often time consuming processes • What is testing for? • To determine if the solution implemented by the program is correct or to find bugs? • It is useful to be able to reason about the correctness of a solution to avoid coding an incorrect solution • The goal of a program is to end with the correct result given that the inputs to the program were as expected • More formally, we want to demonstrate that a program will always terminate with the post-condition satisfied, if the program's pre-conditions hold John Edgar

  6. Pre-Conditions • A pre-condition is an assertion about conditions at the beginning of a method • An assertion is a statement about a condition • More generally: a declaration that is made emphatically (as if no supporting evidence were necessary) • It is part of the "contract" implicit in a method • If the pre-conditions are not true then the method is not guaranteed to produce the desired results • e.g. for binary search, there is a pre-condition that the array or list being searched is sorted, it is not, there is not guarantee that the correct result will be returned • Or, to put it another way, that the post-conditions will hold John Edgar

  7. Post-Conditions • A post-condition is an assertion about conditions at the end of a method • The post-conditions describe the state after the method has been run • They therefore describe the desired output of a method • To prove that an algorithm is correct we need to prove that, if the pre-conditions are correct, following the steps of the algorithm will lead to the post-conditions • We should be able to show how the each step of an algorithm leads to the post-conditions • We can use loop invariants to reason about the correctness of loops John Edgar

  8. Example: Binary Search // PRE: arr is in ascending sorted order // POST: return i such that arr[i] == x if x is // not in arr, returns -1 publicint binary_search(int[] arr, int x) • If the array is sorted (i.e. if the pre-condition is true) then • The correct result is returned (i.e. the post-condition will be true) • If the pre-condition is not true then binary search may not return the correct result John Edgar

  9. Testing Pre and Post-conditions • The pre-conditions and post-conditions act as documentation for a method • They say exactly what a method will do (the post-condition), • and when it can successfully be called (the pre-condition) • When developing a program, broken pre-conditions are important • It means that there is an error somewhere • It is helpful to find the error as close to the responsible code as possible • Pre-conditions and post-conditions can be tested using assertions John Edgar

  10. Assertions • Java provides an assert statement that consist of the keyword, a condition and an optional message string • If the condition is true the statement does nothing • If the condition is false then an exception is thrown, making the program crash • Crashing a program in this way allows errors to be found as soon as possible and as close as possible to where they occurred • This aids in the testing of a program • The assert statements would be removed in the live version of the program John Edgar

  11. Assertion Example • //Assume that len has previously been given a value • double radius = (len - 1) / 2.0; • assert radius > 0 : "radius should be positive"; If radius becomes negative the following error results: java.lang.AssertionError: radius should be positive at examTest.main(examTest.java:28) Exception in thread "main" John Edgar

  12. Using Java Assertions • The assert keyword was an addition to Java 1.4 so you have to make sure that your compiler recognizes it • In Eclipse go to Project, Properties • Select Java Compiler • Click on the Configure Workspace Settings… button and • Go to the Compliance and Classfiles tab. Make sure that 1.4 is selected for all three JDK Compliance dropdown lists • In addition you have tell the virtual machine not to ignore assertions (the default) • In Eclipse, go to the Run configuration, select the Arguments tab and in the lower edit box titled VM Arguments type -ea John Edgar

  13. Example: Binary Search // PRE: arr is in ascending sorted order // POST: return i such that arr[i] == x if x is // not in arr, returns -1 publicint binary_search(int[] arr, int x){ assert is_sorted_asc(arr) : "PRE arr is asc"; // … code to implement binary search … // … which will have returned if x is in arr assert !contains(arr, x) : "POST: "; • Assume that the methods is_sorted_asc and contains exist • contains can be implemented using linear search which is much easier to write than binary search • Assertions are used to test code during development, and will be removed before releasing the program John Edgar

  14. Unit Testing • Test each (non-trivial) function or method in a module or class • Each method's tests should be independent from other methods' tests if possible • The goal is to isolate each part of the program and show that it is correct • Given a set of test cases this makes it easier for programmers to refactor code and test that the module still works correctly • Once a module is complete it allows programmers to focus on integration testing with confidence that the individual modules are sound • Unit testing is part of the Extreme Programming methodology (although it predates it) John Edgar

  15. Unit Testing with Assertions • Using print statements to test the output of methods can be time consuming and is prone to error • The console output has to be checked to ensure that it matches to the expected output of each test • It is easy for the tester to miss an error • Instead assertions can be used to automatically test code • A series of tests should be written for each method, where each test consists of some input and the expected output • An assertion can then be written for each test • There are unit testing tools, such as JUnit John Edgar

  16. Testing Binary Search publicstaticvoid main(String[] args) { int[] nums = {1, 4, 45, 65, 66, 67, 67, 903}; assert binary_search(nums, 1000) == -1; assert binary_search(nums, 0) == -1; assert binary_search(nums, 3) == -1; assert binary_search(nums, 50) == -1; assert binary_search(nums, 1) == 0; assert binary_search(nums, 903) == 7; assert binary_search(nums, 66) == 4; System.out.println("all tests passed"); } John Edgar

  17. Testing Binary Search: Notes • Each assert statement performs one test • If the test passes, nothing happens • If the test fails, the assert throws an error which crashes the program • If desired, the assert statements could also show messages to indicate what each test was doing • No knowledge of the actual algorithm is required to write, or perform, these tests • This is sometimes referred to as black box testing • The tests cover a variety of possibilities • Tests should always include the extreme cases, that is, items near the start or the end of the array, as this is often where bugs are found John Edgar

  18. Loop Invariants • A loop invariant is a boolean expression that is true • Before the loop starts, • After each execution of the loop and • After the loop has finished • Usually this boolean expression includes variables used in the loop • Note that many invariants can be tested, but only useful ones should be chosen! • That is, useful in determining whether or not the post-conditions will hold when the algorithm is terminated John Edgar

  19. Binary Search Loop Invariants • The low index should always be less than or equal to the high index • low <= high • The target (x) should not be in the array from the start of the array to index low – 1 or from index high + 1 to the end of the array • x is not in arr[0], arr[1], arr[low-1] • x is not in arr[high+1], arr[high+2], arr[arr.length-1] • high – low + 1 should always be smaller than it was on the previous iteration • Thinking about these invariants can help in writing a correct loop John Edgar

  20. Complete Binary Search Algorithm publicint binary_search(int[] arr, int x){ int low = 0; int high = arr.length - 1; int mid = 0; while (low <= high){ mid = (low + high) / 2; if(x == arr[mid]){ return mid; } else if(x > arr[mid]){ low = mid + 1; } else { //x < arr[mid] high = mid - 1; } } //while return -1; //x not found } John Edgar

  21. Class Invariants • A class invariant is an invariant on the values of the variables of an object • For example, consider a MatrixPoint object that represents a pixel in TheMatrix, and has variables x and y that represent the x and y coordinates of the pixel • The point must fall within the bounds of TheMatrix • If TheMatrix is w pixels wide and h pixels high the class invariant for the MatrixPoint object would be: • 0 <= x < w && 0 <= y < h • All constructors and mutators should respect class invariants • That is, they should always make sure that class invariants are true John Edgar

More Related