test-driven development for developers: plain and simple
DESCRIPTION
Test-driven development (TDD) is not an easy discipline to establish. However, it provides considerable return on investment for the effort. Rob Myers describes the costs of TDD (the introduction of test-maintenance overhead) and its benefits (greatly improved quality, productivity, and throughput of real value)—but only when the TDD practices are given time to ripen. Rob shares a simple three-step process for establishing the personal and professional discipline required to successfully implement TDD and takes you through a simple yet realistic demo to reveal three core TDD techniques—Triangulation, Fake It, and Obvious Implementation. Rob uses this demo to show how new objects can reveal themselves to developers via "obvious necessity" thus destroying the myth that all TDD design must arise from either specification or refactoring. In this demo, Rob uses Java and JUnit but the principles and techniques described apply to any object-oriented programming efforts in any programming language.TRANSCRIPT
AT7 Concurrent Session 11/14/2013 2:15 PM
"Test-Driven Development for Developers:
Plain and Simple"
Presented by:
Rob Myers Agile Institute
Brought to you by:
340 Corporate Way, Suite 300, Orange Park, FL 32073 888‐268‐8770 ∙ 904‐278‐0524 ∙ [email protected] ∙ www.sqe.com
Rob Myers Agile Institute
Rob Myers is founder of the Agile Institute and a founding member of the Agile Cooperative. With twenty-seven years of professional experience on software development teams, Rob has consulted for leading companies in aerospace, government, medical, software, and financial sectors. He has been training and coaching organizations in Scrum and Extreme Programming (XP) management and development practices since 1999. Rob’s courses—including Essential Test-Driven Development and Essential Agile Principles and Practices—are a blend of enjoyable, interactive, hands-on labs plus practical dialog toward preserving sanity in the workplace. Rob performs short- and long-term coaching to encourage, solidify, and improve the team's agile practices.
9/10/13
1
10 September 2013 © Agile Institute 2008-2013 1
TDD for Developers:
Plain & Simple
Rob Myers for
Agile Development Practices East
14 November 2013
Café
10 September 2013 © Agile Institute 2008-2013 2
9/10/13
2
10 September 2013 © Agile Institute 2008-2013 3
Unit testing is soooo
DEPRESSING
10 September 2013 © Agile Institute 2008-2013 4
TDD is fun, and provides
much more than just unit-tests!
9/10/13
3
10 September 2013 © Agile Institute 2008-2013 5
“The results of the case studies indicate
that the pre-release defect density of the
four products decreased between 40%
and 90% relative to similar projects that
d i d n o t u s e t h e T D D p r a c t i c e .
Subjectively, the teams experienced a
15–35% increase in initial development
time after adopting TDD.” http://research.microsoft.com/en-us/projects/esm/nagappan_tdd.pdf, Nagappan et al,
© Springer Science + Business Media, LLC 2008
10 September 2013 © Agile Institute 2008-2013 6
=
9/10/13
4
10 September 2013 © Agile Institute 2008-2013 7
discipline
10 September 2013 © Agile Institute 2008-2013 8
9/10/13
5
10 September 2013 © Agile Institute 2008-2013 9
TDD Demo
no magic
10 September 2013 © Agile Institute 2008-2013 10
import junit.framework.Assert; import org.junit.Test;
public class SetTests {
@Test public void setStartsOutEmpty() {
Set mySet = new Set();
Assert.assertEquals(0, mySet.size()); }
}
9/10/13
6
requirements & conventions
10 September 2013 © Agile Institute 2008-2013 11
import junit.framework.Assert; import org.junit.Test;
public class SetTests {
@Test
public void setStartsOutEmpty() { Set mySet = new Set();
Assert.assertEquals(0, mySet.size()); }
}
Expected Actual
start simple
To Do q Empty set. q Adding an item. q Adding two different items. q Adding the same item twice.
10 September 2013 © Agile Institute 2008-2013 12
9/10/13
7
specification, and interface
10 September 2013 © Agile Institute 2008-2013 13
import junit.framework.Assert; import org.junit.Test;
public class SetTests {
@Test
public void setStartsOutEmpty() {
Set mySet = new Set();
Assert.assertEquals(0, mySet.size()); }
}
Will not compile. L
“Thank you, but…”
10 September 2013 © Agile Institute 2008-2013 14
package supersets; public class Set { public int size() { throw new RuntimeException("D'oh! Not yet implemented!"); } }
9/10/13
8
“…I want to see it fail successfully”
10 September 2013 © Agile Institute 2008-2013 15
public class Set { public int size() {
return -1; }
}
technique: “Fake It”
10 September 2013 © Agile Institute 2008-2013 16
package supersets;
public class Set {
public int size() {
return 0; }
}
9/10/13
9
a. refactor away duplication
10 September 2013 © Agile Institute 2008-2013 17
@Test public void setStartsOutEmpty() {
Set mySet = new Set();
Assert.assertEquals(0, mySet.size());
}
public class Set { public int size() { return 0; }
}
b. triangulate
10 September 2013 © Agile Institute 2008-2013 18
9/10/13
10
technique: “Triangulation”
10 September 2013 © Agile Institute 2008-2013 19
@Test public void addingItemIncreasesCount() { Set mySet = new Set(); mySet.add("One item"); Assert.assertEquals(1, mySet.size()); }
@Test
public void setStartsOutEmpty() { Set mySet = new Set();
Assert.assertEquals(0, mySet.size());
}
technique: “Obvious Implementation”
10 September 2013 © Agile Institute 2008-2013 20
import java.util.ArrayList; import java.util.List;
public class Set {
private List innerList = new ArrayList();
public int size() {
return innerList.size(); }
public void add(Object element) {
innerList.add(element); }
}
9/10/13
11
maintain (refactor) the tests
10 September 2013 © Agile Institute 2008-2013 21
Set mySet; @Before public void initializeStuffCommonToThisTestClass() { mySet = new Set(); } @Test
public void addingItemIncreasesCount() {
mySet.add("One item"); Assert.assertEquals(1, mySet.size());
}
@Test
public void setStartsOutEmpty() {
Assert.assertEquals(0, mySet.size());
}
now for something interesting
10 September 2013 © Agile Institute 2008-2013 22
@Test public void addingEquivalentItemTwiceAddsItOnlyOnce() { String theString = "Equivalent string"; mySet.add(theString); mySet.add(new String(theString)); Assert.assertEquals(1, mySet.size()); }
9/10/13
12
the new behavior
10 September 2013 © Agile Institute 2008-2013 23
public class Set { private List innerList = new ArrayList();
public int size() {
return innerList.size();
}
public void add(Object element) {
if (!innerList.contains(element)) innerList.add(element);
}
}
next?
To Do q Empty set. q Adding an item. q Adding two different items. q Adding the same item twice.
10 September 2013 © Agile Institute 2008-2013 24
9/10/13
13
10 September 2013 © Agile Institute 2008-2013 25
1. Write one unit test.
2. Build or add to the object under test until everything compiles.
3. Red: Watch the test fail!
4. Green: Make all the tests pass by changing the object under test.
5. Clean: Refactor mercilessly!
6. Repeat.
steps
10 September 2013 © Agile Institute 2008-2013 26
http://PowersOfTwo.agileInstitute.com/
@agilecoach