Download presentation
Presentation is loading. Please wait.
1
Lecture 5: Test-Driven Development Basics
CSE 116/504 – Intro. To Computer Science for Majors II Lecture 5: Test-Driven Development Basics
2
Announcements Normal homework schedule starting with this one
Always due Mondays at 12:45PM (15 min. before class) Use problems to learn concepts before quiz & tests Can always attempt problems before its lecture When the topics seem difficult, do not get too worried Wait for lecture to ask questions, will cover topics then
3
Today’s Goals Continue real-life TDD example: TopHat
Learn test-driven development goals & benefits Think & discuss why do we care about testing? How TDD differs and why it improves code quality Discuss what is an annotation & how used in testing JUnit test case basics & best practices discussed
4
Good Code Key Concept #1
5
Good Code Key Concept #1 Good Code Works
6
Good Code Works
7
Good Code Works
8
Test-Driven Development (TDD)
Very popular technique developing software
9
Test-Driven Development (TDD)
Very popular technique developing software
10
Test-Driven Development (TDD)
Very popular technique developing software Greatly increases programmer productivity Happier programmers also found when using TDD Requires very different approach to coding Requires tests written BEFORE implementations Write stubs (but no code) for class & methods Knowing correct outputs, write tests to check Implement methods to pass your tests (& check often)
11
Common Objection To TDD
But… How could I write tests before I know what the method does?
12
Smart Programmer Responds…
How could you write the code before you know what the method must do?
13
TDD Objections Feels weird to start with tests when you first try…
.. but objections reflect poor programming habits Know method’s outcomes when starting to write… … but you may not know how it will be done
14
Thought Experiment Have new engine uses 100x less gas
New power generation method provides this boost Of the following which test would you want: Belts and axels moved identically with new engine New engine still uses same carburetor & pistons
15
TDD Objections Feels weird to start with tests when you first try…
.. but objections reflect poor programming habits Know method’s outcomes when starting to write… … but you may not know how it will be done Effects, not process, checked by good test cases It might be that you find faster code for method Other methods not rewritten as result of improvement Important that your tests show changes not needed
16
Check method’s results NOT method’s processes
TDD Key Concept #1 Check method’s results NOT method’s processes
17
Why TDD Helps Many benefits when test cases created first
Clarify what method does so coding becomes easier Since written for tests, methods become easier to fix Know when code done by checking if tests pass Studies have found that TDD simplifies debugging Know when bug created by running tests regularly Tests start to fail after writing 1 line: bug on that line Bugs… somewhere(?) when hours pass before testing
18
Unit Testing Library Nearly everyone uses JUnit for unit testing
Tests written in Java so can run anywhere Strong support that make writing tests very easy JUnit support in most IDEs (e.g., Eclipse, IntelliJ, BlueJ) Not limited to Java – xUnit exists for many languages Automation important to allow frequent testing Testing easy – just select “Run As…” “Junit test” Green means good – checking results also very easy Easy to see problems – see red when tests fail
19
JUnit Test Cases Format
Most often write test class for each class Identical to other classes; usually named ____Test As a Java class, can use inheritance & have fields Inheritance & fields not required like any Java class Since ver. 4.0, JUnit’s annotations identify tests Extra information added to show method is test case Annotation added immediately before method
20
JUnit Test Cases Format
Most often write test class for each class Identical to other classes; usually named ____Test As a Java class, can use inheritance & have fields Inheritance & fields not required like any Java class Since ver. 4.0, JUnit’s annotations identify tests Extra information added to show method is test case Annotation added immediately before method No code or comments between annotation & method
21
Writing Test Methods Test methods MUST have @Test annotation
Only non-static void methods can use annotation To be usable, test methods cannot have parameters Use normal Java code to write these test methods Just normal methods; can contain any legal Java code Conditionals and loop statements often are included Can instantiate objects and call methods on objects Other methods can use assert___ & be called by tests
22
JUnit Annotations Loop over each test case in the entire class
JUnit executes all methods Optional methods initialize any data before each test Will have exactly 1 method executed Pass if no crashes & no incorrect asserts occur during test Fails & stops running when assert____ does not pass Executes all methods Also optional, cleans mess made
23
JUnit Annotations Loop over each test case in the entire class
JUnit executes all methods Optional methods initialize any data before each test Will have exactly 1 method executed Pass if no crashes & no incorrect asserts occur during test Fails & stops running when assert____ does not pass Executes all methods Also optional, cleans mess made
24
assert____ Statements
Java statements which actually check results: assertTrue(boolean test) assertFalse(boolean test) assertEquals(X expected, X actual) assertNull(Object objTest) assertNotNull(Object objTest) fail()
25
assert____ Statements
Java statements which actually check results: assertTrue(String message, boolean test) assertFalse(String message, boolean test) assertEquals(String message,X expected, X actual) assertNull(String message, Object objTest) assertNotNull(String message, Object objTest) fail(String message) Can add optional message. Use it when you have additional information for failing test.
26
Outline of (Most) Test Methods
Declare variable(s), create objects, & prep inputs Call the method being tested Use specification to verify returned value correct Check fields for changes matching requirements Should also verify other fields did not change Assert object arguments are correct
27
JUnit Tests Key Concept #2
method should execute AT LEAST 1 assert_____()
28
JUnit Test Case Ordering
1 Place lines into proper order 1. assertEquals(2,actual); 2. al.add(s); al.add(s); 3. int actual = al.size(); 4. ArrayList<String> al = new ArrayList<String>(); String s = “Testing”;
29
JUnit Test Case Ordering
1 Place lines into proper order 1. assertEquals(2,actual); 2. al.add(s); al.add(s); 3. int actual = al.size(); 4. ArrayList<String> al = new ArrayList<String>(); String s = “Testing”; Convince your neighbor your answer is correct
30
JUnit Test Case Ordering
1 Place lines into proper order 1. assertEquals(2,actual); 2. al.add(s); al.add(s); 3. int actual = al.size(); 4. ArrayList<String> al = new ArrayList<String>(); String s = “Testing”;
31
JUnit Test Case Ordering
1 4. ArrayList<String> al = new ArrayList<String>(); String s = “Testing”; 3. int actual = al.size(); 1. assertEquals(2,actual); 2. al.add(s); al.add(s);
32
JUnit Test Case Ordering
1 4. ArrayList<String> al = new ArrayList<String>(); String s = “Testing”; 3. int actual = al.size(); 1. assertEquals(2,actual); 2. al.add(s); al.add(s);
33
JUnit Test Case Ordering
1 4. ArrayList<String> al = new ArrayList<String>(); String s = “Testing”; 3. int actual = al.size(); 1. assertEquals(2,actual); 2. al.add(s); al.add(s);
34
JUnit Test Case Ordering
1 4. ArrayList<String> al = new ArrayList<String>(); String s = “Testing”; 3. int actual = al.size(); 1. assertEquals(2,actual); 2. al.add(s); al.add(s);
35
JUnit Test Case Ordering
1 4. ArrayList<String> al = new ArrayList<String>(); String s = “Testing”; 3. int actual = al.size(); 1. assertEquals(2,actual); 2. al.add(s); al.add(s);
36
JUnit Test Case Ordering
1 4. ArrayList<String> al = new ArrayList<String>(); String s = “Testing”; 3. int actual = al.size(); 3. int actual = al.size(); 2. al.add(s); al.add(s);
37
Reminder
38
JUnit Test Case Ordering
1 4. ArrayList<String> al = new ArrayList<String>(); String s = “Testing”; 2. al.add(s); al.add(s); 3. int actual = al.size(); 1. assertEquals(2,actual);
39
Class To Be Tested public class Operational { private int a, b; public Operational(int fst, int snd) { a = fst; b = snd; } public String multiply() { int product = a * b; return “Product is ”+product; } public String sum() { return “Sum is ”+a+b; } }
40
Class To Be Tested public class Operational { private int a, b; public Operational(int fst, int snd) { a = fst; b = snd; } public String multiply() { int product = a * b; return “Product is ”+product; } public String sum() { return “Sum is ”+a+b; } } This concatenates a & b (like Strings) rather than adding them. So will be 32 and not 5. Our tests need to find this!
41
Starting to Write Test Cases
Traditionally, test class adds “Test” to class name Each case is method annotation public class OperationalTest { @Test public void testMult0() { Operational xByZero = new Operational(3, 0); Operational zeroByX = new Operational(0, 17); assertEquals(“Product is 0”, xByZero.multiply()); assertEquals(“Product is 0”, zeroByX.multiply()); }
42
Starting to Write Test Cases
Traditionally, test class adds “Test” to class name Each case is method annotation public class OperationalTest { @Test public void testMult0() { Operational xByZero = new Operational(3, 0); Operational zeroByX = new Operational(0, 17); assertEquals(“Product is 0”, xByZero.multiply()); assertEquals(“Product is 0”, zeroByX.multiply()); }
43
Starting to Write Test Cases
Traditionally, test class adds “Test” to class name Each case is method annotation public class OperationalTest { @Test public void testMult0() { Operational xByZero = new Operational(3, 0); Operational zeroByX = new Operational(0, 17); assertEquals(“Product is 0”, xByZero.multiply()); assertEquals(“Product is 0”, zeroByX.multiply()); }
44
Bad Tests to Write Only get to know test failed with assertTrue()
@Test public void yuckyButLegal() { Operational xByOne = new Operational(-2, 1); Operational oneByX = new Operational(1, 4); assertTrue(xByOne.multiply() equals(“Product is 2”)); }
45
Bad Tests to Write Only get to know test failed with assertTrue()
@Test public void yuckyButLegal() { Operational xByOne = new Operational(-2, 1); Operational oneByX = new Operational(1, 4); assertTrue(xByOne.multiply() equals(“Product is 2”)); }
46
Better Tests to Write Get more detailed results with assertEquals()
@Test public void muchImproved() { Operational xByOne = new Operational(-2, 1); Operational oneByX = new Operational(1, 4); assertEquals(xByOne.multiply(), “Product is 2”); }
47
Better Tests to Write Get more detailed results with assertEquals()
@Test public void muchImproved() { Operational xByOne = new Operational(-2, 1); Operational oneByX = new Operational(1, 4); assertEquals(xByOne.multiply(), “Product is 2”); }
48
JUnit Tests Key Concept #3
Use assertTrue() & assertFalse() only with boolean variables & methods
49
More Test Gotchas Must be certain assert___ checking code to test
@Test public void whatAmITesting() { Operational xByOne = new Operational(-2, 1); assertEquals(“Product is -2”, “Product is ” + (-2 * 1)); }
50
More Test Gotchas Must be certain assert___ checking code to test
@Test public void whatAmITesting() { Operational xByOne = new Operational(-2, 1); assertEquals(“Product is -2”, “Product is ” + (-2 * 1)); }
51
More Test Gotchas Must be certain assert___ checking code to test
@Test public void whatAmITesting() { Operational xByOne = new Operational(-2, 1); assertEquals(“Product is -2”, “Product is ” + (-2 * 1)); }
52
More Test Gotchas Will this pass?
@Test public void passingIsNotFailing() { Operational xByOne = new Operational(-2, 1); xByOne.sum(); }
53
More Test Gotchas Will this pass?
@Test public void passingIsNotFailing() { Operational xByOne = new Operational(-2, 1); xByOne.sum(); }
54
More Test Gotchas Will this pass?
@Test public void passingIsNotFailing() { Operational xByOne = new Operational(-2, 1); xByOne.sum(); }
55
JUnit Tests Key Concept #2
method should call AT LEAST 1 assert_____()
56
Hardcode Your Checks Hardcode answer in assert___ whenever possible
@Test public void shouldNotPassButDoesPass() { Operational xByOne = new Operational(-2, 1); assertEquals(“Sum is ” , xByOne.sum()); }
57
Hardcode Your Checks Hardcode answer in assert___ whenever possible
@Test public void shouldNotPassButDoesPass() { Operational xByOne = new Operational(-2, 1); assertEquals(“Sum is ” , xByOne.sum()); }
58
Hardcode Your Checks Hardcode answer in assert___ whenever possible
@Test public void canNowFindBug() { Operational xByOne = new Operational(-2, 1); assertEquals(“Sum is -1”, xByOne.sum()); }
59
Select Real JUnit Annotation(s)
@Test @First @Fail @After @TestClass
60
Select Real JUnit Annotation(s)
@Test @First @Fail @After @TestClass Convince your neighbor of the correct answer(s)
61
Select Real JUnit Annotation(s)
@Test @First @Fail @After @TestClass
62
Select Real JUnit Annotation(s)
@Test needed by JUnit to know methods it should run @Test @First @Fail @After @TestClass
63
Select Real JUnit Annotation(s)
JUnit cannot guarantee order methods are run @Test @First @Fail @After @TestClass
64
Select Real JUnit Annotation(s)
fail() is JUnit assertion that method calls to force test to fail @Test @First @Fail @After @TestClass
65
Select Real JUnit Annotation(s)
@After used on method(s) run after each JUnit test method @Test @First @Fail @After @TestClass
66
Select Real JUnit Annotation(s)
I just made this one up @Test @First @Fail @After @TestClass Image from:
67
Select Real JUnit Annotation(s)
@Test @First @Fail @After @TestClass
68
Last Detail Often make assumptions when writing code
True writing code and still true writing test cases Passing != correct; could be no tests were run May not check what you think; care needed writing tests Tests should be written & run before coding Tests better fail, since code has not yet been written! Before wasting time, always check assumptions
69
Last Detail Often make assumptions when writing code
True writing code and still true writing test cases Passing != correct; could be no tests were run May not check what you think; care needed writing tests Tests should be written & run before coding Tests better fail, since code has not yet been written! Before wasting time, always check assumptions
70
Good Code Key Concept #1 Good Code Works
71
Check method’s results NOT method’s processes
TDD Key Concept #1 Check method’s results NOT method’s processes
72
JUnit Tests Key Concept #2
method should execute AT LEAST 1 assert_____()
73
JUnit Tests Key Concept #3
Use assertTrue() & assertFalse() only with boolean variables & methods
74
For Next Lecture Read webpage & section 2.4 – 2.7 for Monday
Going more in depth into writing good JUnit tests How to decide code done when grading no longer occurs Will discuss shortcuts for developing suites of test cases Week #2 homework posted and ready to finish Past add/drop so will always be due on Monday at 12:45
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.