SlideShare ist ein Scribd-Unternehmen logo
1 von 40
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

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 commandsVishvjeet Yadav
 
COMPUTER SCIENCE CLASS 12 PRACTICAL FILE
COMPUTER SCIENCE CLASS 12 PRACTICAL FILECOMPUTER SCIENCE CLASS 12 PRACTICAL FILE
COMPUTER SCIENCE CLASS 12 PRACTICAL FILEAnushka Rai
 
12th CBSE Practical File
12th CBSE Practical File12th CBSE Practical File
12th CBSE Practical FileAshwin Francis
 
C++ L03-Control Structure
C++ L03-Control StructureC++ L03-Control Structure
C++ L03-Control StructureMohammad Shaker
 
C++ L02-Conversion+enum+Operators
C++ L02-Conversion+enum+OperatorsC++ L02-Conversion+enum+Operators
C++ L02-Conversion+enum+OperatorsMohammad 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 cTushar 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_papervandna123
 
FP 201 - Unit 6
FP 201 - Unit 6FP 201 - Unit 6
FP 201 - Unit 6rohassanie
 

Was ist angesagt? (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
 

Ähnlich wie Unit tests for converting integers to CSV format

2 BytesC++ course_2014_c4_ arrays
2 BytesC++ course_2014_c4_ arrays2 BytesC++ course_2014_c4_ arrays
2 BytesC++ course_2014_c4_ arrayskinan keshkeh
 
Lab. Programs in C
Lab. Programs in CLab. Programs in C
Lab. Programs in CSaket Pathak
 
VIT351 Software Development VI Unit2
VIT351 Software Development VI Unit2VIT351 Software Development VI Unit2
VIT351 Software Development VI Unit2YOGESH 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 ReviewerAndrey Karpov
 
Python programming workshop session 2
Python programming workshop session 2Python programming workshop session 2
Python programming workshop session 2Abdul 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 duoThe 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 errorsPVS-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.inTIB 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.pdfaccess2future1
 
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 3karmuhtam
 
20.1 Java working with abstraction
20.1 Java working with abstraction20.1 Java working with abstraction
20.1 Java working with abstractionIntro 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.pptxAnkitaVerma776806
 

Ähnlich wie Unit tests for converting integers to CSV format (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
 

Mehr von Kevlin Henney

The Case for Technical Excellence
The Case for Technical ExcellenceThe Case for Technical Excellence
The Case for Technical ExcellenceKevlin Henney
 
Empirical Development
Empirical DevelopmentEmpirical Development
Empirical DevelopmentKevlin Henney
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that LetterKevlin Henney
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that LetterKevlin Henney
 
Solid Deconstruction
Solid DeconstructionSolid Deconstruction
Solid DeconstructionKevlin 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 AwayKevlin Henney
 
Structure and Interpretation of Test Cases
Structure and Interpretation of Test CasesStructure and Interpretation of Test Cases
Structure and Interpretation of Test CasesKevlin Henney
 
Refactoring to Immutability
Refactoring to ImmutabilityRefactoring to Immutability
Refactoring to ImmutabilityKevlin Henney
 
Turning Development Outside-In
Turning Development Outside-InTurning Development Outside-In
Turning Development Outside-InKevlin Henney
 
Giving Code a Good Name
Giving Code a Good NameGiving Code a Good Name
Giving Code a Good NameKevlin 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 QuadrantKevlin Henney
 

Mehr von 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
 

Kürzlich hochgeladen

Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 

Kürzlich hochgeladen (20)

Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 

Unit tests for converting integers to CSV format

  • 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