Introduc)on to tes)ng with JUnit Workshop 3
We have to deal with errors Early errors are usually syntax errors. The compiler will spot these. Later errors are usually logic errors. The compiler cannot help with these. Also known as bugs. Some logical errors have no immediately obvious manifesta)on. Commercial soeware is rarely error free. Objects First with Java - A Practical Introduction using BlueJ, David J. Barnes, Michael Kölling
Preven)on vs Detec)on (Developer vs Maintainer) We can lessen the likelihood of errors. Use soeware engineering techniques, like encapsula)on. We can improve the chances of detec)on. Use soeware engineering prac)ces, like modulariza)on and documenta)on. We can develop detec)on skills. Objects First with Java - A Practical Introduction using BlueJ, David J. Barnes, Michael Kölling
Tes)ng and debugging These are crucial skills. Testing searches for the presence of errors. Debugging searches for the source of errors. The manifestation of an error may well occur some distance from its source. Objects First with Java - A Practical Introduction using BlueJ, David J. Barnes,
JUNIT
JUnit JUnit is a Java test framework Test cases are methods that contain tests Test classes contain test methods Assertions are used to assert expected method results Fixtures are used to support mul)ple tests Objects First with Java - A Practical Introduction using BlueJ, David J. Barnes, Michael Kölling
JUnit de facto standard unit testing framework written by Erich Gamma and Kent Beck bundled in most IDEs www.junit.org useful to have one complete test suite the programmers can run with a pass fail result automatic quality assurance: when the code changes, test cases are rerun to check that nothing breaks 7
Automated Testing Tests must run automatically without human participation (beyond launching the test suite, and maybe not even that) Results should be pass/fail Test failures need to be blindingly obvious Tests must be reproducible and consistent 8
What s in a test case? Unit test cases have the following form: 1. describe the method s inputs 2. describe the expected outputs 3. call the method and observe actual output 4. compare expected with actual and report 9
Coding a test case in JUnit4 @Test! public void testgetareanormal()! {! //1. describe input! Rectangle r1 = new Rectangle(3,4);!! //2. describe expected output(s)! int expected = 12;!! //3. call the method! int actual = r1.getarea();!! //4. compare actual output with expected (AEEA)! assertequals(expected, actual);! }! 10
Before and After every test case public void setup() throws Exception {!!!/* TODO create objects/common variables for tests! * setup is called before EACH test case is run!! */!!}!!!public void teardown() throws Exception {!! /* TODO reset or release objects, eg. normal=null;! * to garbage collect old test object! * teardown is called after EACH test case is run! * NOT USUALLY USED FOR CITS1001 tests! */!!}! 11
How a test suite is executed 1. setup method is executed 2. the first test method in the class is executed 3. teardown method is executed 4. setup method is executed 5. the second test method in the class is executed 6. teardown method is executed Con)nue un)l all test cases are executed. IMPORTANT each test case is independent of previous tests 12
Examples See labs and projects 13
When does expected = actual? To compare any variables of the 8 Java primi)ve types (boolean, byte, short, int, long, char, float, double) assertequals(expected, actual) First argument (op)onal) is a string that is printed if the asser)on fails assertequals(message, expected, actual)! 14
Straight- forward comparisons for basic types public static void!! assertequals(int expected, int actual)!! assertequals(boolean expected, boolean actual)! assertequals(byte expected, byte actual)! assertequals(char expected, char actual)! assertequals(short expected, short actual)! assertequals(long expected, long actual)! 15
Floating point arithmetic As always with floa)ng point arithme)c (double or float), you want to avoid direct equality comparisons. public static void assertequals(!! double expected, double actual,! double tolerance)! For example, assertequals(0.552, 0.510, 0.1) is true but assertequals(0.552, 0.510, 0.01) is false since the values are equivalent within a tolerance of ± 0.1 but not to 2 decimal places. 16
How to Test Objects What is the expected result of this test? public void testobjequality() {!!Rectangle r1 = new Rectangle(2,4);!!Rectangle r2 = new Rectangle(2,4);!!assertEquals(r1,r2);!!}! 17
Testing Objects Problem JUnit responds with junit.framework.asser)onfailederror: resize OK expected:<rectangle@913fe2> but was:<rectangle@1f934ad> Problem: we have tested for equivalence of the references to the 2 rectangle objects, not the contents of those rectangle objects 18
Solution Write a local equivalence tester for the class you are testing private void testrectangleequality(rectangle r1, Rectangle r2) {!! // Test height and width!! assertequals( Not same height, r1.getheight(), r2.getheight());! assertequals( Not same width,r1.getwidth(),r2.getwidth());! }! Aside: This test method terminates after the first failure, so if both tests fail only the first is reported 19
Testing methods that throw exceptions public void testgridempty() {! try {! new Grid(new int[0][0]);! }! fail("illegalargumentexception should be thrown for [0][0] grid");! }! catch (IllegalArgumentException iae) {! //test passed:! //correct exception thrown! }! 20
More assertions See http://junit.sourceforge.net/javadoc/org/junit/ Assert.html For example, assertarrayequals assertnull assertnotsame asserttrue assertfalse 21
CHOOSING TEST CASES
Choosing Test Cases Typical cases Sanity check that method code works as expected, but try to choose tricky cases anyway! Special cases and Boundary cases Most errors occur for boundary values, eg empty or full array, -1,0,1 etc. Exceptional cases Illegal input, divide by 0, un-initialized parameters 23
Tes)ng fundamentals Understand what the unit should do its contract. You will be looking for violations. Use positive tests and negative tests. Test boundaries. Zero, One, Full. Search an empty collection. Add to a full collection. Objects First with Java - A Practical Introduction using BlueJ, David J. Barnes, Michael Kölling
Unit tes)ng Each unit of an application may be tested. Method, class, module (package in Java). Can (should) be done during development. Finding and fixing early lowers development costs (e.g. programmer time). A test suite is built up. Objects First with Java - A Practical Introduction using BlueJ, David J. Barnes, Michael Kölling
Plan your test cases using tables Inputs TYPICAL height=3, width=4 hscale=2.0, wscale=0.5 BOUNDARY height=3, width=4 hscale=1.0, wscale=1.0 EXCEPTIONAL height=3, width=4 hscale=0.5, wscale=0.0 Expected Output height=6, width=2 height=3, width=4 height=1?, width=0? 26
Verbal walkthroughs Explain to someone else what the code is doing. They might spot the error. The process of explaining might help you to spot it for yourself. Group- based processes exist for conduc)ng formal walkthroughs or inspec3ons. Objects First with Java - A Practical Introduction using BlueJ, David J. Barnes, Michael Kölling
Also, ask questions Useful when testing someone else s class eg. a library class Ask: What happens if you do XXX? Is an exception thrown? If so, which one? Is null treated as zero? Is null returned? Something else? Write a test that determines the answer to your question(s) 28
More ways to test your code Acceptance Tests Use a main method to execute a sequence of steps (method calls) corresponding to client s use cases Good for visual testing of methods with graphical displays or user interfaces (terminal of graphic) Coverage Testing How much of your code is executed by your test cases? For example, try to execute all branches or all paths through the code 29
Pragmatic Unit Testing Andrew Hunt and David Thomas (available online) The Right-BICEP method (chapter 4) Right - Are the results right? B - Are all the boundary conditions CORRECT? I - Can you check inverse relationships? C - Can you cross-check results using other means? E - Can you force error conditions to happen? P - Are performance characteristics within bounds? 30
Print statements The most popular technique. No special tools required. All programming languages support them. Only effec)ve if the right methods are documented. Output may be voluminous! Turning off and on requires forethought. Objects First with Java - A Practical Introduction using BlueJ, David J. Barnes, Michael Kölling
Choosing a test strategy Be aware of the available strategies. Choose strategies appropriate to the point of development. Automate whenever possible. Reduces tedium. Reduces human error. Makes (re)tes)ng more likely. Objects First with Java - A Practical Introduction using BlueJ, David J. Barnes, Michael Kölling
Review Errors are a fact of life in programs. Good software development techniques can reduce their occurrence. Testing and debugging skills are essential. Make testing a habit. Automate testing where possible. Continually repeat tests. Practice a range of debugging skills. Objects First with Java - A Practical Introduction using BlueJ, David J. Barnes, Michael Kölling