SlideShare a Scribd company logo
Programming with GUTs 
@KevlinHenney 
kevlin@curbralan.com
When you write unit tests, TDD- style or after your development, you scrutinize, you think, and often you prevent problems without even encountering a test failure. 
Michael Feathers "The Flawed Theory Behind Unit Testing" http://michaelfeathers.typepad.com/michael_feathers_blog/2008/06/the-flawed-theo.html
Very many people say "TDD" when they really mean, "I have good unit tests" ("I have GUTs"?). 
Ron Jeffries tried for years to explain what this was, but we never got a catch-phrase for it, and now TDD is being watered down to mean GUTs. 
Alistair Cockburn "The modern programming professional has GUTs" http://alistair.cockburn.us/The+modern+programming+professional+has+GUTs
size_t ints_to_csv( 
const int * to_write, size_t how_many, 
char * output, size_t length);
size_t ints_to_csv( 
const int * to_write, size_t how_many, char * output, size_t length) 
{ 
size_t result = 0; 
if(length != 0) 
{ 
if(how_many == 0) 
{ 
output[0] = '0'; 
} 
else 
{ 
for(size_t which = 0; which != how_many && result != length; ++which) 
{ 
result += 
snprintf( 
output + result, length - result, 
which == 0 ? "%i" : ",%i", 
to_write[which]); 
} 
result = result > length - 1 ? length - 1 : result; 
} 
} 
return result; 
}
extern "C" size_t ints_to_csv( 
const int * to_write, size_t how_many, char * output, size_t length) 
{ 
size_t result = 0; 
if(length != 0) 
{ 
output[length - 1] = '0'; 
std::ostrstream buffer(output, length - 1); 
for(size_t which = 0; which != how_many; ++which) 
buffer << (which == 0 ? "" : ",") << to_write[which]; 
buffer << std::ends; 
result = std::strlen(output); 
} 
return result; 
}
function 
test
void test_ints_to_csv() 
{ 
size_t written = ints_to_csv(NULL, 0, NULL, 0); 
assert(written == 0); 
const int input[] = { 42 }; 
written = ints_to_csv(input, 1, NULL, 0); 
assert(written == 0); 
char output[3] = "+++"; 
written = ints_to_csv(NULL, 0, output, sizeof output); 
assert(written == 0); 
assert(output[0] == '0'); 
memcpy(output, "+++", sizeof output); 
written = ints_to_csv(input, 1, output, sizeof output); 
assert(written == 2); 
assert(strcmp(output, "42") == 0); 
... 
}
void test_ints_to_csv() 
{ 
// no values from null to null output writes nothing 
size_t written = ints_to_csv(NULL, 0, NULL, 0); 
assert(written == 0); 
// value to null output writes nothing 
const int input[] = { 42 }; 
written = ints_to_csv(input, 1, NULL, 0); 
assert(written == 0); 
// no values to sufficient output writes empty 
char output[3] = "+++"; 
written = ints_to_csv(NULL, 0, output, sizeof output); 
assert(written == 0); 
assert(output[0] == '0'); 
// positive value to sufficient output writes value without sign 
memcpy(output, "+++", sizeof output); 
written = ints_to_csv(input, 1, output, sizeof output); 
assert(written == 2); 
assert(strcmp(output, "42") == 0); 
... 
}
void test_ints_to_csv() 
{ 
// no values from null to null output writes nothing 
{ 
size_t written = ints_to_csv(NULL, 0, NULL, 0); 
assert(written == 0); 
} 
// value to null output writes nothing 
{ 
const int input[] = { 42 }; 
size_t written = ints_to_csv(input, 1, NULL, 0); 
assert(written == 0); 
} 
// no values to sufficient output writes empty 
{ 
char output[3] = "+++"; 
size_t written = ints_to_csv(NULL, 0, output, sizeof output); 
assert(written == 0); 
assert(output[0] == '0'); 
} 
// positive value to sufficient output writes value without sign 
{ 
const int input[] = { 42 }; 
char output[3] = "+++"; 
size_t written = ints_to_csv(input, 1, output, sizeof output); 
assert(written == 2); 
assert(strcmp(output, "42") == 0); 
}
void no_values_from_null_to_null_output_writes_nothing() 
{ 
size_t written = ints_to_csv(NULL, 0, NULL, 0); 
assert(written == 0); 
} 
void value_to_null_output_writes_nothing() 
{ 
const int input[] = { 42 }; 
size_t written = ints_to_csv(input, 1, NULL, 0); 
assert(written == 0); 
} 
void no_values_to_sufficient_output_writes_empty() 
{ 
char output[3] = "+++"; 
size_t written = ints_to_csv(NULL, 0, output, sizeof output); 
assert(written == 0); 
assert(output[0] == '0'); 
} 
void positive_value_to_sufficient_output_writes_value_without_sign() 
{ 
const int input[] = { 42 }; 
char output[3] = "+++"; 
size_t written = ints_to_csv(input, 1, output, sizeof output); 
assert(written == 2); 
assert(strcmp(output, "42") == 0); 
} 
void negative_value_to_sufficient_output_writes_value_with_sign() 
{ 
const int input[] = { -42 }; 
char output[4] = "++++"; 
size_t written = ints_to_csv(input, 1, output, sizeof output); 
assert(written == 3); 
assert(strcmp(output, "-42") == 0); 
} 
void value_to_insufficient_output_writes_truncated_value() 
{ 
const int input[] = { 42 }; 
char output[2] = "++"; 
size_t written = ints_to_csv(input, 1, output, sizeof output); 
assert(written == 1); 
assert(strcmp(output, "4") == 0); 
} 
void multiple_values_to_sufficient_output_writes_comma_separated_values() 
{ 
const int input[] = { 42, -273, 0, 7 }; 
char output[12] = "++++++++++++"; 
size_t written = ints_to_csv(input, 4, output, sizeof output); 
assert(written == 11); 
assert(strcmp(output, "42,-273,0,7") == 0); 
} 
void multiple_values_to_insufficient_output_writes_truncated_value_sequence() 
{ 
const int input[] = { 42, -273, 0, 7 }; 
char output[9] = "+++++++++"; 
size_t written = ints_to_csv(input, 4, output, sizeof output); 
assert(written == 8); 
assert(strcmp(output, "42,-273,") == 0); 
}
void no_values_from_null_to_null_output_writes_nothing() 
{ 
... 
} 
void value_to_null_output_writes_nothing() 
{ 
... 
} 
void no_values_to_sufficient_output_writes_empty() 
{ 
... 
} 
void positive_value_to_sufficient_output_writes_value_without_sign() 
{ 
... 
} 
void negative_value_to_sufficient_output_writes_value_with_sign() 
{ 
... 
} 
void value_to_insufficient_output_writes_truncated_value() 
{ 
... 
} 
void multiple_values_to_sufficient_output_writes_comma_separated_values() 
{ 
... 
} 
void multiple_values_to_insufficient_output_writes_truncated_value_sequence() 
{ 
... 
}
function 
test 
test 
test
size_t ints_to_csv( const int * to_write, size_t how_many, char * output, size_t length); 
 No values from null to null output writes nothing 
 Value to null output writes nothing 
 No values to sufficient output writes empty 
 Positive value to sufficient output writes value without sign 
 Negative value to sufficient output writes value with sign 
 Value to insufficient output writes truncated value 
 Multiple values to sufficient output writes comma separated values 
 Multiple values to insufficient output writes truncated value sequence
Tests that are not written with their role as specifications in mind can be very confusing to read. The difficulty in understanding what they are testing can greatly reduce the velocity at which a codebase can be changed. 
Nat Pryce and Steve Freeman "Are Your Tests Really Driving Your Development?"
Propositions are vehicles for stating how things are or might be.
Thus only indicative sentences which it makes sense to think of as being true or as being false are capable of expressing propositions.
public static boolean isLeapYear(int year) ...
yearsNotDivisibleBy4... 
yearsDivisibleBy4ButNotBy100... 
yearsDivisibleBy100ButNotBy400... 
yearsDivisibleBy400...
Years_not_divisible_by_4_... 
Years_divisible_by_4_but_not_by_100_... 
Years_divisible_by_100_but_not_by_400_... 
Years_divisible_by_400_...
Years_not_divisible_by_4_should_not_be_leap_years 
Years_divisible_by_4_but_not_by_100_should_be_leap_years 
Years_divisible_by_100_but_not_by_400_should_not_be_leap_years 
Years_divisible_by_400_should_be_leap_years
Years_not_divisible_by_4_are_not_leap_years 
Years_divisible_by_4_but_not_by_100_are_leap_years 
Years_divisible_by_100_but_not_by_400_are_not_leap_years 
Years_divisible_by_400_are_not_leap_years
Years_not_divisible_by_4_are_not_leap_years 
Years_divisible_by_4_but_not_by_100_are_leap_years 
Years_divisible_by_100_but_not_by_400_are_not_leap_years 
Years_divisible_by_400_are_not_leap_years
Years_not_divisible_by_4_are_not_leap_years 
Years_divisible_by_4_but_not_by_100_are_leap_years 
Years_divisible_by_100_but_not_by_400_are_not_leap_years 
Years_divisible_by_400_are_not_leap_years
A test case should be just that: it should correspond to a single case.
public class Leap_year_spec 
{ 
public static class A_year_is_a_leap_year 
{ 
@Test public void If_it_is_divisible_by_4_but_not_by_100()  
@Test public void If_it_is_divisible_by_400()  
} 
public static class A_year_is_not_a_leap_year 
{ 
@Test public void If_it_is_not_divisible_by_4()  
@Test public void If_it_is_divisible_by_100_but_not_by_400()  
} 
}
public class Leap_year_spec 
{ 
public static class A_year_is_a_leap_year 
{ 
@Test public void If_it_is_divisible_by_4_but_not_by_100()  
@Test public void If_it_is_divisible_by_400()  
} 
public static class A_year_is_not_a_leap_year 
{ 
@Test public void If_it_is_not_divisible_by_4()  
@Test public void If_it_is_divisible_by_100_but_not_by_400()  
} 
}
method 
test 
test 
test 
method 
method
public class RecentlyUsedList 
{ 
... 
public RecentlyUsedList() ... 
public int Count 
{ 
get... 
} 
public string this[int index] 
{ 
get... 
} 
public void Add(string newItem) ... 
... 
}
[TestFixture] 
public class RecentlyUsedListTests 
{ 
[Test] 
public void TestConstructor() ... 
[Test] 
public void TestCountGet() ... 
[Test] 
public void TestIndexerGet() ... 
[Test] 
public void TestAdd() ... 
... 
}
method 
test 
test 
test 
method 
method 
test 
test
namespace RecentlyUsedList_spec 
{ 
[TestFixture] 
public class A_new_list 
{ 
[Test] public void Is_empty()  
} 
[TestFixture] 
public class An_empty_list 
{ 
[Test] public void Retains_a_single_addition()  
[Test] public void Retains_unique_additions_in_stack_order()  
} 
[TestFixture] 
public class A_non_empty_list 
{ 
[Test] public void Is_unchanged_when_head_item_is_readded()  
[Test] public void Moves_non_head_item_to_head_when_it_is_readded()  
} 
[TestFixture] 
public class Any_list 
{ 
[Test] public void Rejects_addition_of_null_items()  
[Test] public void Rejects_indexing_past_its_end()  
[Test] public void Rejects_negative_indexing()  
} 
}
namespace RecentlyUsedList_spec { [TestFixture] public class A_new_list { [Test] public void Is_empty()  } [TestFixture] public class An_empty_list { [Test] public void Retains_a_single_addition()  [Test] public void Retains_unique_additions_in_stack_order()  } [TestFixture] public class A_non_empty_list { [Test] public void Is_unchanged_when_head_item_is_readded()  [Test] public void Moves_non_head_item_to_head_when_it_is_readded()  } [TestFixture] public class Any_list { [Test] public void Rejects_addition_of_null_items()  [Test] public void Rejects_indexing_past_its_end()  [Test] public void Rejects_negative_indexing()  } }
So who should you be writing the tests for? For the person trying to understand your code. 
Good tests act as documentation for the code they are testing. They describe how the code works. For each usage scenario, the test(s): 
Describe the context, starting point, or preconditions that must be satisfied 
Illustrate how the software is invoked 
Describe the expected results or postconditions to be verified 
Gerard Meszaros "Write Tests for People"
namespace RecentlyUsedList_spec 
{ 
[TestFixture] 
public class A_new_list ... 
[TestFixture] 
public class An_empty_list 
{ 
[Test] 
public void Retains_a_single_addition( 
[Values("Prague", "Oslo", "Bristol")] string addend) 
{ 
var items = new RecentlyUsedList(); // Given... 
items.Add(addend); // When... 
Assert.AreEqual(1, items.Count); // Then... 
Assert.AreEqual(addend, list[0]); 
} 
[Test] public void Retains_unique_additions_in_stack_order()  
} 
[TestFixture] 
public class A_non_empty_list ... 
[TestFixture] 
public class Any_list ... 
}
Less unit testing dogma. 
More unit testing karma. 
Alberto Savoia 
"The Way of Testivus" 
http://www.artima.com/weblogs/viewpost.jsp?thread=203994

More Related Content

What's hot

Useful c programs
Useful c programsUseful c programs
Useful c programs
MD SHAH FAHAD
 
Computer Science Practical Science C++ with SQL commands
Computer Science Practical Science C++ with SQL commandsComputer Science Practical Science C++ with SQL commands
Computer Science Practical Science C++ with SQL commands
Vishvjeet Yadav
 
Implementing string
Implementing stringImplementing string
Implementing string
mohamed sikander
 
COMPUTER SCIENCE CLASS 12 PRACTICAL FILE
COMPUTER SCIENCE CLASS 12 PRACTICAL FILECOMPUTER SCIENCE CLASS 12 PRACTICAL FILE
COMPUTER SCIENCE CLASS 12 PRACTICAL FILE
Anushka Rai
 
12th CBSE Practical File
12th CBSE Practical File12th CBSE Practical File
12th CBSE Practical File
Ashwin Francis
 
C++ L03-Control Structure
C++ L03-Control StructureC++ L03-Control Structure
C++ L03-Control Structure
Mohammad Shaker
 
Arrays
ArraysArrays
Arrays
fahadshakeel
 
C++ L02-Conversion+enum+Operators
C++ L02-Conversion+enum+OperatorsC++ L02-Conversion+enum+Operators
C++ L02-Conversion+enum+Operators
Mohammad Shaker
 
Oops practical file
Oops practical fileOops practical file
Oops practical fileAnkit Dixit
 
An imperative study of c
An imperative study of cAn imperative study of c
An imperative study of c
Tushar B Kute
 
Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output) Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output)
Aman Deep
 
2014 computer science_question_paper
2014 computer science_question_paper2014 computer science_question_paper
2014 computer science_question_paper
vandna123
 
Computer Programming- Lecture 6
Computer Programming- Lecture 6Computer Programming- Lecture 6
Computer Programming- Lecture 6
Dr. Md. Shohel Sayeed
 
3. chapter ii
3. chapter ii3. chapter ii
3. chapter ii
Chhom Karath
 
Cquestions
Cquestions Cquestions
Cquestions
mohamed sikander
 
Stl algorithm-Basic types
Stl algorithm-Basic typesStl algorithm-Basic types
Stl algorithm-Basic types
mohamed sikander
 
Arrays
ArraysArrays
FP 201 - Unit 6
FP 201 - Unit 6FP 201 - Unit 6
FP 201 - Unit 6rohassanie
 

What's hot (20)

C program
C programC program
C program
 
Useful c programs
Useful c programsUseful c programs
Useful c programs
 
Computer Science Practical Science C++ with SQL commands
Computer Science Practical Science C++ with SQL commandsComputer Science Practical Science C++ with SQL commands
Computer Science Practical Science C++ with SQL commands
 
Implementing string
Implementing stringImplementing string
Implementing string
 
COMPUTER SCIENCE CLASS 12 PRACTICAL FILE
COMPUTER SCIENCE CLASS 12 PRACTICAL FILECOMPUTER SCIENCE CLASS 12 PRACTICAL FILE
COMPUTER SCIENCE CLASS 12 PRACTICAL FILE
 
12th CBSE Practical File
12th CBSE Practical File12th CBSE Practical File
12th CBSE Practical File
 
C++ L03-Control Structure
C++ L03-Control StructureC++ L03-Control Structure
C++ L03-Control Structure
 
Arrays
ArraysArrays
Arrays
 
Array notes
Array notesArray notes
Array notes
 
C++ L02-Conversion+enum+Operators
C++ L02-Conversion+enum+OperatorsC++ L02-Conversion+enum+Operators
C++ L02-Conversion+enum+Operators
 
Oops practical file
Oops practical fileOops practical file
Oops practical file
 
An imperative study of c
An imperative study of cAn imperative study of c
An imperative study of c
 
Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output) Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output)
 
2014 computer science_question_paper
2014 computer science_question_paper2014 computer science_question_paper
2014 computer science_question_paper
 
Computer Programming- Lecture 6
Computer Programming- Lecture 6Computer Programming- Lecture 6
Computer Programming- Lecture 6
 
3. chapter ii
3. chapter ii3. chapter ii
3. chapter ii
 
Cquestions
Cquestions Cquestions
Cquestions
 
Stl algorithm-Basic types
Stl algorithm-Basic typesStl algorithm-Basic types
Stl algorithm-Basic types
 
Arrays
ArraysArrays
Arrays
 
FP 201 - Unit 6
FP 201 - Unit 6FP 201 - Unit 6
FP 201 - Unit 6
 

Similar to Programming with GUTs

C tutorial
C tutorialC tutorial
2 BytesC++ course_2014_c4_ arrays
2 BytesC++ course_2014_c4_ arrays2 BytesC++ course_2014_c4_ arrays
2 BytesC++ course_2014_c4_ arrays
kinan keshkeh
 
C tutorial
C tutorialC tutorial
C tutorial
Anurag Sukhija
 
Lab. Programs in C
Lab. Programs in CLab. Programs in C
Lab. Programs in C
Saket Pathak
 
Computation Chapter 4
Computation Chapter 4Computation Chapter 4
Computation Chapter 4
Inocentshuja Ahmad
 
VIT351 Software Development VI Unit2
VIT351 Software Development VI Unit2VIT351 Software Development VI Unit2
VIT351 Software Development VI Unit2
YOGESH SINGH
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
Andrey Karpov
 
Python programming workshop session 2
Python programming workshop session 2Python programming workshop session 2
Python programming workshop session 2
Abdul Haseeb
 
Developer Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duoDeveloper Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duo
The Software House
 
Some examples of the 64-bit code errors
Some examples of the 64-bit code errorsSome examples of the 64-bit code errors
Some examples of the 64-bit code errors
PVS-Studio
 
C C++ tutorial for beginners- tibacademy.in
C C++ tutorial for beginners- tibacademy.inC C++ tutorial for beginners- tibacademy.in
C C++ tutorial for beginners- tibacademy.in
TIB Academy
 
Complete DB code following the instructions Implement the D.pdf
Complete DB code following the instructions Implement the D.pdfComplete DB code following the instructions Implement the D.pdf
Complete DB code following the instructions Implement the D.pdf
access2future1
 
R Language
R LanguageR Language
R Language
ShwetDadhaniya1
 
COM1407: Arrays
COM1407: ArraysCOM1407: Arrays
COM1407: Arrays
Hemantha Kulathilake
 
Programming Fundamentals Arrays and Strings
Programming Fundamentals   Arrays and Strings Programming Fundamentals   Arrays and Strings
Programming Fundamentals Arrays and Strings
imtiazalijoono
 
Data structure week 3
Data structure week 3Data structure week 3
Data structure week 3
karmuhtam
 
Arrays in c
Arrays in cArrays in c
Arrays in c
vampugani
 
20.1 Java working with abstraction
20.1 Java working with abstraction20.1 Java working with abstraction
20.1 Java working with abstraction
Intro C# Book
 
the refernce of programming C notes ppt.pptx
the refernce of programming C notes ppt.pptxthe refernce of programming C notes ppt.pptx
the refernce of programming C notes ppt.pptx
AnkitaVerma776806
 

Similar to Programming with GUTs (20)

C tutorial
C tutorialC tutorial
C tutorial
 
2 BytesC++ course_2014_c4_ arrays
2 BytesC++ course_2014_c4_ arrays2 BytesC++ course_2014_c4_ arrays
2 BytesC++ course_2014_c4_ arrays
 
C tutorial
C tutorialC tutorial
C tutorial
 
Lab. Programs in C
Lab. Programs in CLab. Programs in C
Lab. Programs in C
 
Computation Chapter 4
Computation Chapter 4Computation Chapter 4
Computation Chapter 4
 
VIT351 Software Development VI Unit2
VIT351 Software Development VI Unit2VIT351 Software Development VI Unit2
VIT351 Software Development VI Unit2
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
 
pointers 1
pointers 1pointers 1
pointers 1
 
Python programming workshop session 2
Python programming workshop session 2Python programming workshop session 2
Python programming workshop session 2
 
Developer Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duoDeveloper Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duo
 
Some examples of the 64-bit code errors
Some examples of the 64-bit code errorsSome examples of the 64-bit code errors
Some examples of the 64-bit code errors
 
C C++ tutorial for beginners- tibacademy.in
C C++ tutorial for beginners- tibacademy.inC C++ tutorial for beginners- tibacademy.in
C C++ tutorial for beginners- tibacademy.in
 
Complete DB code following the instructions Implement the D.pdf
Complete DB code following the instructions Implement the D.pdfComplete DB code following the instructions Implement the D.pdf
Complete DB code following the instructions Implement the D.pdf
 
R Language
R LanguageR Language
R Language
 
COM1407: Arrays
COM1407: ArraysCOM1407: Arrays
COM1407: Arrays
 
Programming Fundamentals Arrays and Strings
Programming Fundamentals   Arrays and Strings Programming Fundamentals   Arrays and Strings
Programming Fundamentals Arrays and Strings
 
Data structure week 3
Data structure week 3Data structure week 3
Data structure week 3
 
Arrays in c
Arrays in cArrays in c
Arrays in c
 
20.1 Java working with abstraction
20.1 Java working with abstraction20.1 Java working with abstraction
20.1 Java working with abstraction
 
the refernce of programming C notes ppt.pptx
the refernce of programming C notes ppt.pptxthe refernce of programming C notes ppt.pptx
the refernce of programming C notes ppt.pptx
 

More from Kevlin Henney

Program with GUTs
Program with GUTsProgram with GUTs
Program with GUTs
Kevlin Henney
 
The Case for Technical Excellence
The Case for Technical ExcellenceThe Case for Technical Excellence
The Case for Technical Excellence
Kevlin Henney
 
Empirical Development
Empirical DevelopmentEmpirical Development
Empirical Development
Kevlin Henney
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
Kevlin Henney
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
Kevlin Henney
 
Solid Deconstruction
Solid DeconstructionSolid Deconstruction
Solid Deconstruction
Kevlin Henney
 
Get Kata
Get KataGet Kata
Get Kata
Kevlin Henney
 
Procedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went AwayProcedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went Away
Kevlin Henney
 
Structure and Interpretation of Test Cases
Structure and Interpretation of Test CasesStructure and Interpretation of Test Cases
Structure and Interpretation of Test Cases
Kevlin Henney
 
Agility ≠ Speed
Agility ≠ SpeedAgility ≠ Speed
Agility ≠ Speed
Kevlin Henney
 
Refactoring to Immutability
Refactoring to ImmutabilityRefactoring to Immutability
Refactoring to Immutability
Kevlin Henney
 
Old Is the New New
Old Is the New NewOld Is the New New
Old Is the New New
Kevlin Henney
 
Turning Development Outside-In
Turning Development Outside-InTurning Development Outside-In
Turning Development Outside-In
Kevlin Henney
 
Giving Code a Good Name
Giving Code a Good NameGiving Code a Good Name
Giving Code a Good Name
Kevlin Henney
 
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Kevlin Henney
 
Thinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation QuadrantThinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation Quadrant
Kevlin Henney
 
Code as Risk
Code as RiskCode as Risk
Code as Risk
Kevlin Henney
 
Software Is Details
Software Is DetailsSoftware Is Details
Software Is Details
Kevlin Henney
 
Game of Sprints
Game of SprintsGame of Sprints
Game of Sprints
Kevlin Henney
 
Good Code
Good CodeGood Code
Good Code
Kevlin Henney
 

More from Kevlin Henney (20)

Program with GUTs
Program with GUTsProgram with GUTs
Program with GUTs
 
The Case for Technical Excellence
The Case for Technical ExcellenceThe Case for Technical Excellence
The Case for Technical Excellence
 
Empirical Development
Empirical DevelopmentEmpirical Development
Empirical Development
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
 
Solid Deconstruction
Solid DeconstructionSolid Deconstruction
Solid Deconstruction
 
Get Kata
Get KataGet Kata
Get Kata
 
Procedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went AwayProcedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went Away
 
Structure and Interpretation of Test Cases
Structure and Interpretation of Test CasesStructure and Interpretation of Test Cases
Structure and Interpretation of Test Cases
 
Agility ≠ Speed
Agility ≠ SpeedAgility ≠ Speed
Agility ≠ Speed
 
Refactoring to Immutability
Refactoring to ImmutabilityRefactoring to Immutability
Refactoring to Immutability
 
Old Is the New New
Old Is the New NewOld Is the New New
Old Is the New New
 
Turning Development Outside-In
Turning Development Outside-InTurning Development Outside-In
Turning Development Outside-In
 
Giving Code a Good Name
Giving Code a Good NameGiving Code a Good Name
Giving Code a Good Name
 
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
 
Thinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation QuadrantThinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation Quadrant
 
Code as Risk
Code as RiskCode as Risk
Code as Risk
 
Software Is Details
Software Is DetailsSoftware Is Details
Software Is Details
 
Game of Sprints
Game of SprintsGame of Sprints
Game of Sprints
 
Good Code
Good CodeGood Code
Good Code
 

Recently uploaded

Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
Matt Welsh
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
Ortus Solutions, Corp
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
Globus
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
XfilesPro
 
Designing for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesDesigning for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web Services
KrzysztofKkol1
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
informapgpstrackings
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
vrstrong314
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Globus
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
Software Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdfSoftware Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdf
MayankTawar1
 
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Hivelance Technology
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 

Recently uploaded (20)

Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
 
Designing for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesDesigning for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web Services
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
Software Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdfSoftware Testing Exam imp Ques Notes.pdf
Software Testing Exam imp Ques Notes.pdf
 
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
Multiple Your Crypto Portfolio with the Innovative Features of Advanced Crypt...
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 

Programming with GUTs

  • 1. Programming with GUTs @KevlinHenney kevlin@curbralan.com
  • 2.
  • 3. When you write unit tests, TDD- style or after your development, you scrutinize, you think, and often you prevent problems without even encountering a test failure. Michael Feathers "The Flawed Theory Behind Unit Testing" http://michaelfeathers.typepad.com/michael_feathers_blog/2008/06/the-flawed-theo.html
  • 4. Very many people say "TDD" when they really mean, "I have good unit tests" ("I have GUTs"?). Ron Jeffries tried for years to explain what this was, but we never got a catch-phrase for it, and now TDD is being watered down to mean GUTs. Alistair Cockburn "The modern programming professional has GUTs" http://alistair.cockburn.us/The+modern+programming+professional+has+GUTs
  • 5. size_t ints_to_csv( const int * to_write, size_t how_many, char * output, size_t length);
  • 6. size_t ints_to_csv( const int * to_write, size_t how_many, char * output, size_t length) { size_t result = 0; if(length != 0) { if(how_many == 0) { output[0] = '0'; } else { for(size_t which = 0; which != how_many && result != length; ++which) { result += snprintf( output + result, length - result, which == 0 ? "%i" : ",%i", to_write[which]); } result = result > length - 1 ? length - 1 : result; } } return result; }
  • 7. extern "C" size_t ints_to_csv( const int * to_write, size_t how_many, char * output, size_t length) { size_t result = 0; if(length != 0) { output[length - 1] = '0'; std::ostrstream buffer(output, length - 1); for(size_t which = 0; which != how_many; ++which) buffer << (which == 0 ? "" : ",") << to_write[which]; buffer << std::ends; result = std::strlen(output); } return result; }
  • 9. void test_ints_to_csv() { size_t written = ints_to_csv(NULL, 0, NULL, 0); assert(written == 0); const int input[] = { 42 }; written = ints_to_csv(input, 1, NULL, 0); assert(written == 0); char output[3] = "+++"; written = ints_to_csv(NULL, 0, output, sizeof output); assert(written == 0); assert(output[0] == '0'); memcpy(output, "+++", sizeof output); written = ints_to_csv(input, 1, output, sizeof output); assert(written == 2); assert(strcmp(output, "42") == 0); ... }
  • 10. void test_ints_to_csv() { // no values from null to null output writes nothing size_t written = ints_to_csv(NULL, 0, NULL, 0); assert(written == 0); // value to null output writes nothing const int input[] = { 42 }; written = ints_to_csv(input, 1, NULL, 0); assert(written == 0); // no values to sufficient output writes empty char output[3] = "+++"; written = ints_to_csv(NULL, 0, output, sizeof output); assert(written == 0); assert(output[0] == '0'); // positive value to sufficient output writes value without sign memcpy(output, "+++", sizeof output); written = ints_to_csv(input, 1, output, sizeof output); assert(written == 2); assert(strcmp(output, "42") == 0); ... }
  • 11. void test_ints_to_csv() { // no values from null to null output writes nothing { size_t written = ints_to_csv(NULL, 0, NULL, 0); assert(written == 0); } // value to null output writes nothing { const int input[] = { 42 }; size_t written = ints_to_csv(input, 1, NULL, 0); assert(written == 0); } // no values to sufficient output writes empty { char output[3] = "+++"; size_t written = ints_to_csv(NULL, 0, output, sizeof output); assert(written == 0); assert(output[0] == '0'); } // positive value to sufficient output writes value without sign { const int input[] = { 42 }; char output[3] = "+++"; size_t written = ints_to_csv(input, 1, output, sizeof output); assert(written == 2); assert(strcmp(output, "42") == 0); }
  • 12. void no_values_from_null_to_null_output_writes_nothing() { size_t written = ints_to_csv(NULL, 0, NULL, 0); assert(written == 0); } void value_to_null_output_writes_nothing() { const int input[] = { 42 }; size_t written = ints_to_csv(input, 1, NULL, 0); assert(written == 0); } void no_values_to_sufficient_output_writes_empty() { char output[3] = "+++"; size_t written = ints_to_csv(NULL, 0, output, sizeof output); assert(written == 0); assert(output[0] == '0'); } void positive_value_to_sufficient_output_writes_value_without_sign() { const int input[] = { 42 }; char output[3] = "+++"; size_t written = ints_to_csv(input, 1, output, sizeof output); assert(written == 2); assert(strcmp(output, "42") == 0); } void negative_value_to_sufficient_output_writes_value_with_sign() { const int input[] = { -42 }; char output[4] = "++++"; size_t written = ints_to_csv(input, 1, output, sizeof output); assert(written == 3); assert(strcmp(output, "-42") == 0); } void value_to_insufficient_output_writes_truncated_value() { const int input[] = { 42 }; char output[2] = "++"; size_t written = ints_to_csv(input, 1, output, sizeof output); assert(written == 1); assert(strcmp(output, "4") == 0); } void multiple_values_to_sufficient_output_writes_comma_separated_values() { const int input[] = { 42, -273, 0, 7 }; char output[12] = "++++++++++++"; size_t written = ints_to_csv(input, 4, output, sizeof output); assert(written == 11); assert(strcmp(output, "42,-273,0,7") == 0); } void multiple_values_to_insufficient_output_writes_truncated_value_sequence() { const int input[] = { 42, -273, 0, 7 }; char output[9] = "+++++++++"; size_t written = ints_to_csv(input, 4, output, sizeof output); assert(written == 8); assert(strcmp(output, "42,-273,") == 0); }
  • 13. void no_values_from_null_to_null_output_writes_nothing() { ... } void value_to_null_output_writes_nothing() { ... } void no_values_to_sufficient_output_writes_empty() { ... } void positive_value_to_sufficient_output_writes_value_without_sign() { ... } void negative_value_to_sufficient_output_writes_value_with_sign() { ... } void value_to_insufficient_output_writes_truncated_value() { ... } void multiple_values_to_sufficient_output_writes_comma_separated_values() { ... } void multiple_values_to_insufficient_output_writes_truncated_value_sequence() { ... }
  • 15. size_t ints_to_csv( const int * to_write, size_t how_many, char * output, size_t length);  No values from null to null output writes nothing  Value to null output writes nothing  No values to sufficient output writes empty  Positive value to sufficient output writes value without sign  Negative value to sufficient output writes value with sign  Value to insufficient output writes truncated value  Multiple values to sufficient output writes comma separated values  Multiple values to insufficient output writes truncated value sequence
  • 16. Tests that are not written with their role as specifications in mind can be very confusing to read. The difficulty in understanding what they are testing can greatly reduce the velocity at which a codebase can be changed. Nat Pryce and Steve Freeman "Are Your Tests Really Driving Your Development?"
  • 17.
  • 18. Propositions are vehicles for stating how things are or might be.
  • 19. Thus only indicative sentences which it makes sense to think of as being true or as being false are capable of expressing propositions.
  • 20. public static boolean isLeapYear(int year) ...
  • 24.
  • 28. A test case should be just that: it should correspond to a single case.
  • 29. public class Leap_year_spec { public static class A_year_is_a_leap_year { @Test public void If_it_is_divisible_by_4_but_not_by_100()  @Test public void If_it_is_divisible_by_400()  } public static class A_year_is_not_a_leap_year { @Test public void If_it_is_not_divisible_by_4()  @Test public void If_it_is_divisible_by_100_but_not_by_400()  } }
  • 30. public class Leap_year_spec { public static class A_year_is_a_leap_year { @Test public void If_it_is_divisible_by_4_but_not_by_100()  @Test public void If_it_is_divisible_by_400()  } public static class A_year_is_not_a_leap_year { @Test public void If_it_is_not_divisible_by_4()  @Test public void If_it_is_divisible_by_100_but_not_by_400()  } }
  • 31. method test test test method method
  • 32. public class RecentlyUsedList { ... public RecentlyUsedList() ... public int Count { get... } public string this[int index] { get... } public void Add(string newItem) ... ... }
  • 33. [TestFixture] public class RecentlyUsedListTests { [Test] public void TestConstructor() ... [Test] public void TestCountGet() ... [Test] public void TestIndexerGet() ... [Test] public void TestAdd() ... ... }
  • 34. method test test test method method test test
  • 35. namespace RecentlyUsedList_spec { [TestFixture] public class A_new_list { [Test] public void Is_empty()  } [TestFixture] public class An_empty_list { [Test] public void Retains_a_single_addition()  [Test] public void Retains_unique_additions_in_stack_order()  } [TestFixture] public class A_non_empty_list { [Test] public void Is_unchanged_when_head_item_is_readded()  [Test] public void Moves_non_head_item_to_head_when_it_is_readded()  } [TestFixture] public class Any_list { [Test] public void Rejects_addition_of_null_items()  [Test] public void Rejects_indexing_past_its_end()  [Test] public void Rejects_negative_indexing()  } }
  • 36. namespace RecentlyUsedList_spec { [TestFixture] public class A_new_list { [Test] public void Is_empty()  } [TestFixture] public class An_empty_list { [Test] public void Retains_a_single_addition()  [Test] public void Retains_unique_additions_in_stack_order()  } [TestFixture] public class A_non_empty_list { [Test] public void Is_unchanged_when_head_item_is_readded()  [Test] public void Moves_non_head_item_to_head_when_it_is_readded()  } [TestFixture] public class Any_list { [Test] public void Rejects_addition_of_null_items()  [Test] public void Rejects_indexing_past_its_end()  [Test] public void Rejects_negative_indexing()  } }
  • 37.
  • 38. So who should you be writing the tests for? For the person trying to understand your code. Good tests act as documentation for the code they are testing. They describe how the code works. For each usage scenario, the test(s): Describe the context, starting point, or preconditions that must be satisfied Illustrate how the software is invoked Describe the expected results or postconditions to be verified Gerard Meszaros "Write Tests for People"
  • 39. namespace RecentlyUsedList_spec { [TestFixture] public class A_new_list ... [TestFixture] public class An_empty_list { [Test] public void Retains_a_single_addition( [Values("Prague", "Oslo", "Bristol")] string addend) { var items = new RecentlyUsedList(); // Given... items.Add(addend); // When... Assert.AreEqual(1, items.Count); // Then... Assert.AreEqual(addend, list[0]); } [Test] public void Retains_unique_additions_in_stack_order()  } [TestFixture] public class A_non_empty_list ... [TestFixture] public class Any_list ... }
  • 40. Less unit testing dogma. More unit testing karma. Alberto Savoia "The Way of Testivus" http://www.artima.com/weblogs/viewpost.jsp?thread=203994