TDD, BDD, ATDD are all methodologies that enable incremental design that is suitable for Agile environments. It seems that every day a new xDD methodology is born with the promise to be better than what came before. Should you use behaviour-driven tests or plain old unit tests? Which methodology is better? And how exactly would it benefit the development life cycle?
In this session, Dror will help to sort out the various methodologies – explaining where they came from, the tools they use, and discussing how and when to use each one. Here we will once and for all answer the question as to whether or not there’s one “DD” to rule them all.
3. A history lesson Methodologies
Books! Books!
Books!
Tools overview
4.
5.
6. little a few flaws
lot many more flaws
feature works
customer's requirements
7. 1991 1994 1997 2000 2002
Taligent
framework
NUnit 2.0Kent Beck
writes first
version of
SUnit test
framework*
Kent Beck &
Erich Gamma
create JUnit
During a flight
to OOPSLA
Michael
Features
ports JUnit to
C++ (CppUnit)
8. Test Suite
Fixture
Test Case
Test Case
Test Case
Test Case
Test Case
Fixture
Test Case
Test Case
Fixture
Test Case
Test Case
Test Case
public class BeforeAndAfter {
@Before
public void setUp() {
}
@After
public void tearDown() {
}
@Test
public void test1() {
}
@Test
public void test2() {
}
}
16. @Test
public void Pass1_ReturnI() {
cut = new ArabicToRoman();
String result = cut.convert(1);
assertEquals("I", result);
}
public class ArabicToRoman {
}
17. @Test
public void Pass1_ReturnI() {
cut = new ArabicToRoman();
String result = cut.convert(1);
assertEquals("I", result);
}
public class ArabicToRoman {
public String convert(int num) {
return null;
}
}
18. @Test
public void Pass1_ReturnI() {
cut = new ArabicToRoman();
String result = cut.convert(1);
assertEquals("I", result);
}
public class ArabicToRoman {
public String convert(int num) {
return null;
}
}
19. @Test
public void Pass1_ReturnI() {
cut = new ArabicToRoman();
String result = cut.convert(1);
assertEquals("I", result);
}
public class ArabicToRoman {
public String convert(int num) {
return “I”;
}
}
20. @Test
public void Pass1_ReturnI() {
cut = new ArabicToRoman();
String result = cut.convert(1);
assertEquals("I", result);
}
public class ArabicToRoman {
public String convert(int num) {
return “I”;
}
}
21. @Test
public void Pass1_ReturnI() {
cut = new ArabicToRoman();
String result = cut.convert(1);
assertEquals("I", result);
}
@Test
public void Pass2_ReturnII() {
cut = new ArabicToRoman();
String result = cut.convert(2);
assertEquals("II", result);
}
public class ArabicToRoman {
public String convert(int num) {
return “I”;
}
}
22. @Test
public void Pass1_ReturnI() {
cut = new ArabicToRoman();
String result = cut.convert(1);
assertEquals("I", result);
}
@Test
public void Pass2_ReturnII() {
cut = new ArabicToRoman();
String result = cut.convert(2);
assertEquals("II", result);
}
public class ArabicToRoman {
public String convert(int num) {
return “I”;
}
}
23. @Test
public void Pass1_ReturnI() {
cut = new ArabicToRoman();
String result = cut.convert(1);
assertEquals("I", result);
}
@Test
public void Pass2_ReturnII() {
cut = new ArabicToRoman();
String result = cut.convert(2);
assertEquals("II", result);
}
public class ArabicToRoman {
public String convert(int num) {
if(i == 2)
return "II";
return "I";
}
}
24. @Test
public void Pass1_ReturnI() {
cut = new ArabicToRoman();
String result = cut.convert(1);
assertEquals("I", result);
}
@Test
public void Pass2_ReturnII() {
cut = new ArabicToRoman();
String result = cut.convert(2);
assertEquals("II", result);
}
public class ArabicToRoman {
public String convert(int num) {
if(i == 2)
return "II";
return "I";
}
}
25. @Test
public void Pass1_ReturnI() {
cut = new ArabicToRoman();
String result = cut.convert(1);
assertEquals("I", result);
}
@Test
public void Pass2_ReturnII() {
cut = new ArabicToRoman();
String result = cut.convert(2);
assertEquals("II", result);
}
public class ArabicToRoman {
public String convert(int num) {
result = new StringBuilder();
for(int i = 0 ; i < num ; i++)
{
result.append("I");
}
return result.toString();
}
}
37. 1996 2002 2002 2003
Automated tests
are part of Extreme
Programming.
Ward Cunningham
publishes Fit
Bob Martin
combines Fit with
Wikis tocreate
Fitnesse
Kent Beck briefly
mentions ATDD in
“TDD: By Example”
but dismisses it as
impractical
40. Unit tests Acceptance tests
Fast Slow
No side effects Side effects
Simple to run Dependent on environment
Test single “unit of work” Test single scenario/feature
Written by developers Written by customers
Verify that code works Overall system works as required
Test must pass before check-in Test may only pass when feature is
done
Fake other units Fake other systems
41.
42. numerator Denominator quotient?
10 2 5.0
12.6 3 4.2
100 4 33
org/FitNesse.FullReferenceGuide.UserGuide.WritingAcceptanceTests.FixtureCode
public class Division {
private double numerator,
denominator;
public void setNumerator(double
numerator) {
this.numerator = numerator;
}
public void setDenominator(double
denominator) {
this.denominator = denominator;
}
public double quotient() {
return numerator/denominator;
}
}
54. less of a wax-on, wax-off process of
gradual mastery than a series of blind alleys…
presentTDD in a way
that gets straight to the good stuff and avoids all the
pitfalls.
60. public class TraderSteps{
private TradingService service;
private Stock stock;
@Given("a stock and a threshold of $threshold")
public void aStock(double threshold) {
stock = service.newStock("STK", threshold);
}
@When("the stock is traded at price $price")
public void theStockIsTraded(double price){
stock.tradeAt(price);
}
@Then("the alert status is $status")
public void theAlertStatusIs($status){
assertThat(stock.getStatus().Name(), equalTo(status));
}
}
Scenario: A trader is alerted of status
Given a stock and a threshold of 15.0
When stock is traded at 5.0
Then the alert status should be off
61. Feature: Addition
In order to avoid silly mistakes
As a math idiot
I want to be told the sum of two numbers
Scenario: Add two numbers
Given I have entered 50 into the calculator
And I have entered 70 into the calculator
When I press add
Then the result should be 120 on the screen
From: https://cukes.info/
62. describe Stack do
it "should return a blank instance" do
Stack.new.should == {}
end
it "element is added to the stack on top of the stack" do
stack = Stack.new
stack.push 'a value'
stack.pop.should == 'a value'
end
end
Stack
should return a blank instance
element is added to the stack on top of the stack
63.
64. [Test]
public void OutOfStorageWhileCreatingFileAndExactFilesToMakeRoom()
{
var fakeSystemInfo = A.Fake<ISystemInfo>();
A.CallTo(() => fakeSystemInfo.GetFreeDiskSpaceInBytes()).Returns(0);
var logfiles = new[]
{
new LogFile
{
Name = "file-1.log",
Size = 50000
},
new LogFile
{
Name = "file-2.log",
Size = 50000
}
};
var fakeLogFolder = A.Fake<ISharedStorageFolder>();
A.CallTo(() => fakeLogFolder.GetFiles()).Returns(logfiles);
var logFileWriter = new LogFileWriter(fakeSystemInfo, fakeLogFolder);
logFileWriter.Write("some message");
A.CallTo(() => fakeLogFolder.DeleteFile("file-1.log")).MustHaveHappened();
A.CallTo(() => fakeLogFolder.DeleteFile("file-2.log")).MustHaveHappened();
}
65. SCENARIO("First roll is strike")
{
GIVEN("Bowled strike on first turn")
{
Game game;
game.Roll(10);
WHEN("Next roll is spare then roll five")
{
game.Roll(3);
game.Roll(7);
game.Roll(5);
RollSeveral(game, 15, 0);
THEN("Total score is 40")
{
REQUIRE(game.Score() == 40);
}
}
WHEN("Next two rolls are strike then gutter balls")
{
game.Roll(10);
game.Roll(10);
RollSeveral(game, 16, 0);
THEN("Total score is 60")
{
REQUIRE(game.Score() == 60);
}
}
}
}
72. They're just both useful to have in your back
pocket as you go around trying to write decent
software to solve useful problems.
But I bet
that's what Kent Beck would say if you asked him
whatTDD was all about.
Dan North, DefiningTDD,
https://groups.google.com/forum/#!msg/behaviordrivendevelopment/OQnb3APpUJk/RklRiyEKde4J
Never write a single line of code unless you have a failing automated test.
Eliminate duplication.
BDD is essentially Test Domain Driven Design
Business readable + writable
Similar to what ATDD had to offer closer to developers
2005 as an experiment by Steven Baker, with early contributions from Dave Astels and Aslak Hellesøy.
RSpec 1.0 was released in May of 2007
Rspec 3 was released in June 2014
Need actual example
So what are those good habits?
Specifically, I think those good habits are:
Working outside-in, starting from a business or organisational goal
Using examples to clarify requirements
Developing and using a ubiquitous language