Slides - CSE Buffalo
Download
Report
Transcript Slides - CSE Buffalo
CSE 116/504 – Intro. To Computer Science for Majors II
LECTURE 2:
TEST-DRIVEN DEVELOPMENT
BASICS
Announcements
CSE Distinguished Speaker Series tomorrow
Talk will be from 3:30 – 4:30 in Student Union 201
Dr. Wendi Heinzelman is expert in energy usage
Discuss pioneering work on wireless & mobile networks
Announcements
Homework problems keyed to week's lectures
Material from Monday's lecture in problem #1
Problem #2 on Wednesday's lecture topics & materials
Question in problem #3 uses topics from Friday
Can always attempt problems before its lecture
When the topics seem difficult, do not get too worried
Autolab up and running, so could start problems #1 & #2
Announcements
26% of class signed up for Piazza already
If you are not one of them, what are you waiting for?
Several helpful discussions already underway
This week’s recitations optional; for help on Eclipse
Next week will be expected to create projects & use JARs
Take advantage of opportunity to learn from the UTAs
Especially for Mondays, please select your recitation
Today’s Goals
Before used in grading, check TopHat works
(Real-life TDD example to show how this helps, btw)
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
Where Are You Located?
A. Davis 338L
B. Tropical Island
C. Norton 112
D. Baldy 21
E. Not sure
What is Your Major?
A. Comp. Sci.
B. Comp. Engineering
C. Other Engineering
D. Other Science
E. None of the above
F. Norton 112
Previous Coding Experience?
A. CSE115 only
B. CSE115 & CSE113
C. CSE115 & other
class(es)
D. CSE 115 & <1 yr work
E. CSE 115 & ≥1 yr work
F. Norton 112
Useful Code Key Concept #1
Useful Code Key Concept #1
Code that
cannot compile
Useful Code Key Concept #1
Code that
cannot compile
Good Code Key Concept #1
Good Code Key Concept #1
Good Code Works
Good Code Works
Test-Driven Development (TDD)
Very popular technique developing software
Test-Driven Development (TDD)
Very popular technique developing software
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
2. Knowing correct outputs, write tests to check
3. Implement methods to pass your tests (& check often)
1.
Common Objection To TDD
But…
How could I
write tests
before I know
what the
method does?
Smart Programmer Responds…
How could you
write the code
before you know
what the
method must do?
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
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
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
TDD Key Concept #1
Check
method’s results
NOT
method’s processes
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
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
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
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
Writing Test Methods
Test methods MUST have @Test annotation
Non-static, void methods only for JUnit to work
By same logic, 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
JUnit Annotations
Loop until all test cases in class are executed
JUnit executes all methods marked @Before
Optional methods initialize any data before each test
Run exactly 1 method labeled @Test executed
Pass if no crashes & no incorrect asserts occur during test
Fails & stops running when assert____ does not pass
Executes all methods marked @After
Also optional, cleans mess made by @Before
JUnit Annotations
method labeled @Test executed
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()
assert____ Statements
Java statements which actually check results:
String message
String message
String message
String message
String message
String message
Can add
optional message.
Use it when you
have additional
information
for failing test.
Statements Performing Checks
assertEquals(
expected, X actual)
assertFalse(
@Test method
should
le exp,
doubleexecute
act,double
lean test) 1 or more
assert_____.
olean test)
assertNull(
ect objTest)
assertEquals(
assertEquals(
assertTrue(
at exp, float act, float tol)
Results only show if
assertNotNull(Object objTest)
fail()
assertion failed.
tol)
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;
}
}
Class To Be Tested
public String sum() {
return “Sum is ”+a+b;
}
This concatenates a & b
(like Strings) rather than
adding them. So 3 + 2 will
be 32 and not 5.
Our tests need to find this!
Starting to Write Test Cases
Traditionally, test class adds “Test” to class name
Each case is method having @Test 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());
}
Starting to Write Test Cases
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());
}
Starting to Write Test Cases
@Test
public void testMult0()
Operational xByZero =
Operational zeroByX =
assertEquals(“Product
assertEquals(“Product
}
{
new Operational(3, 0);
new Operational(0, 17);
is 0”, xByZero.multiply());
is 0”, zeroByX.multiply());
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”));
}
Bad Tests to Write
@Test
public void yuckyButLegal() {
Operational xByOne = new Operational(-2, 1);
Operational oneByX = new Operational(1, 4);
assertTrue(xByOne.multiply()
.equals(“Product is 2”));
}
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”);
}
Better Tests to Write
@Test
public void muchImproved() {
Operational xByOne = new Operational(-2, 1);
Operational oneByX = new Operational(1, 4);
assertEquals(xByOne.multiply(),
“Product is 2”);
}
JUnit Tests Key Concept #1
Use assertTrue()
& assertFalse()
only with boolean
variables & methods
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));
}
More Test Gotchas
@Test
public void whatAmITesting() {
Operational xByOne = new Operational(-2, 1);
assertEquals(“Product is -2”,
“Product is ” + (-2 * 1));
}
More Test Gotchas
@Test
public void whatAmITesting() {
Operational xByOne = new Operational(-2, 1);
assertEquals(“Product is -2”,
“Product is ” + (-2 * 1));
}
More Test Gotchas
Will this pass?
@Test
public void passingIsNotFailing() {
Operational xByOne = new Operational(-2, 1);
xByOne.sum();
}
More Test Gotchas
Will this pass?
@Test
public void passingIsNotFailing() {
Operational xByOne = new Operational(-2, 1);
xByOne.sum();
}
More Test Gotchas
Will this pass?
@Test
public void passingIsNotFailing() {
Operational xByOne = new Operational(-2, 1);
xByOne.sum();
}
JUnit Tests Key Concept #2
Every @Test method
should call
AT LEAST 1
assert_____()
Hardcode Your Checks
Hardcode answer in assert___ whenever possible
@Test
public void shouldNotPassButDoesPass() {
Operational xByOne = new Operational(-2, 1);
assertEquals(“Sum is ” + -2 + 1, xByOne.sum());
}
Hardcode Your Checks
Hardcode answer in assert___ whenever possible
@Test
public void shouldNotPassButDoesPass() {
Operational xByOne = new Operational(-2, 1);
assertEquals(
, xByOne.sum());
}
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());
}
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
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
For Next Lecture
Read sections 1.1 – 1.6 from textbook for Friday
Helping review Java and knock off rust from break
Optional recitation this week to learn Eclipse
Useful practice, since required for homeworks & project
Week #1 homework posted and ready to start
Due to drop/add, this’s week due next Thursday (2/9)