SlideShare a Scribd company logo
Structure and
Interpretation
of Test Cases
@KevlinHenney
Structure and Interpretation of Test Cases
Programs must be
written for people to
read, and only
incidentally for
machines to execute.
Structure and Interpretation of Test Cases
Write Tests for People
Gerard Meszaros
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.
Gerard Meszaros
Very many people say "TDD"
when they really mean, "I have
good unit tests" ("I have GUTs"?).
Alistair Cockburn
The modern programming professional has GUTs
good unit tests" ("I have GUTs
A unit test is a test of behaviour
whose success or failure is wholly
determined by the correctness of
the test and the correctness of
the unit under test.
Kevlin Henney
https://www.theregister.co.uk/2007/07/28/what_are_your_units/
Structure and Interpretation of Test Cases
Unit testable
Necessarily not unit testable
Should be unit testable... but isn’t
The programmer in me made unit testing more
about applying and exercising frameworks.
I had essentially reduced my concept of unit
testing to the basic mechanics of exercising
xUnit to verify the behavior of my classes.
My mindset had me thinking far too narrowly
about what it meant to write good unit tests.
Tod Golding
Tapping into Testing Nirvana
about what it meant to write good unit tests
From time to time I hear people
asking what value of test coverage
(also called code coverage) they
should aim for, or stating their
coverage levels with pride.
Such statements miss the point.
Martin Fowler
http://martinfowler.com/bliki/TestCoverage.html
I expect a high level of coverage.
Sometimes managers require one.
There's a subtle difference.
Brian Marick
http://martinfowler.com/bliki/TestCoverage.html
Structure and Interpretation of Test Cases
public static bool IsLeapYear(int year) 
[Test]
public void Test() 
[Test]
public void TestIsLeapYear() 
[Test]
public void TestIsLeapYearIsCorrect() 
[Test]
public void Test1() 
[Test]
public void Test2() 
[Test]
public void TestLeapYears() 
[Test]
public void TestNonLeapYears() 
[Test]
public void TestLeapYears()
{
Assert.IsTrue(IsLeapYear(2016));
Assert.IsTrue(IsLeapYear(2000));
}
[Test]
public void TestNonLeapYears() 
[Test]
public void Test2016IsALeapYear() 
[Test]
public void Test2000IsALeapYear() 
[Test]
public void Test2018IsNotALeapYear() 
[Test]
public void Test1900IsNotALeapYear() 
[Test]
public void _2016IsALeapYear() 
[Test]
public void _2000IsALeapYear() 
[Test]
public void _2018IsNotALeapYear() 
[Test]
public void _1900IsNotALeapYear() 
[Test]
public void _2016_is_a_leap_year() 
[Test]
public void _2000_is_a_leap_year() 
[Test]
public void _2018_is_not_a_leap_year() 
[Test]
public void _1900_is_not_a_leap_year() 
_2016_is_a_leap_year
_2000_is_a_leap_year
_2018_is_not_a_leap_year
_1900_is_not_a_leap_year
_2020_is_a_leap_year
_2400_is_a_leap_year
_2019_is_not_a_leap_year
_2100_is_not_a_leap_year
Years_divisible_by_4_are_leap_years
Years_divisible_by_400_are_leap_years
Years_not_divisible_by_4_are_not_leap_years
Years_divisible_by_100_are_not_leap_years
Years_not_divisible_by_4_are_not_leap_years
Years_divisible_by_4_are_leap_years
Years_divisible_by_100_are_not_leap_years
Years_divisible_by_400_are_leap_years
Years_not_divisible_by_4_are_not_leap_years
Years_divisible_by_4_but_not_by_100_are_leap_year
Years_divisible_by_100_but_not_by_400_are_not_lea
Years_divisible_by_400_are_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_leap_years
IsLeapYear_YearNotDivisibleBy4_ReturnsFalse
IsLeapYear_YearDivisibleBy4ButNotBy100_ReturnsTrue
IsLeapYear_YearDivisibleBy100ButNotBy400_ReturnsFalse
IsLeapYear_YearDivisibleBy400_ReturnsTrue
Structure and Interpretation of Test Cases
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.
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_leap_years
public static bool IsLeapYear(int year)
{
return
year % 4 == 0 &&
year % 100 != 0 ||
year % 400 == 0;
}
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_leap_years
public static bool IsLeapYear(int year)
{
return year % 4 == 0;
}
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_leap_years
For tests to drive development they must
do more than just test that code performs
its required functionality: they must clearly
express that required functionality to the
reader.
That is, they must be clear specifications
of the required functionality.
Nat Pryce & Steve Freeman
Are your tests really driving your development?
namespace Leap_year_spec
{
[TestFixture]
public 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() 
}
[TestFixture]
public 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() 
}
}
namespace Leap_year_spec
{
[TestFixture]
public 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() 
}
[TestFixture]
public 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() 
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year 
[TestFixture]
public class A_year_is_not_a_leap_year
{
[Test]
public void if_it_is_not_divisible_by_4()
{
Assert.IsFalse(IsLeapYear(2018));
}
[Test]
public void if_it_is_divisible_by_100_but_not_by_400()
{
Assert.IsFalse(IsLeapYear(1900));
}
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year 
[TestFixture]
public class A_year_is_not_a_leap_year
{
[Test]
public void if_it_is_not_divisible_by_4()
{
Assert.IsFalse(isLeapYear(2018));
}
[Test]
public void if_it_is_divisible_by_100_but_not_by_400()
{
Assert.IsFalse(isLeapYear(1900));
}
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year 
[TestFixture]
public class A_year_is_not_a_leap_year
{
[Test]
public void if_it_is_not_divisible_by_4()
{
Assert.IsFalse(isLeapYear(42));
}
[Test]
public void if_it_is_divisible_by_100_but_not_by_400()
{
Assert.IsFalse(isLeapYear(100));
}
}
}
Structure and Interpretation of Test Cases
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year 
[TestFixture]
public class A_year_is_not_a_leap_year
{
[Test]
public void if_it_is_not_divisible_by_4()
{
Assert.IsFalse(IsLeapYear(2018));
Assert.IsFalse(IsLeapYear(2017));
Assert.IsFalse(IsLeapYear(42));
Assert.IsFalse(IsLeapYear(1));
}
[Test]
public void if_it_is_divisible_by_100_but_not_by_400() 
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year 
[TestFixture]
public class A_year_is_not_a_leap_year
{
[TestCase(2018)]
[TestCase(2017)]
[TestCase(42)]
[TestCase(1)]
public void if_it_is_not_divisible_by_4(int year)
{
Assert.IsFalse(IsLeapYear(year));
}
[Test]
public void if_it_is_divisible_by_100_but_not_by_400() 
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year 
[TestFixture]
public class A_year_is_not_a_leap_year
{
[Test]
public void if_it_is_not_divisible_by_4(
[Values(2018, 2017, 42, 1)] int year)
{
Assert.IsFalse(IsLeapYear(year));
}
[Test]
public void if_it_is_divisible_by_100_but_not_by_400() 
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year
{
[Test]
public void if_it_is_divisible_by_4_but_not_by_100(
[Values(2016, 1984, 4)] int year) 
[Test]
public void if_it_is_divisible_by_400(
[Range(400, 2400, 400)] int year) 
}
[TestFixture]
public class A_year_is_not_a_leap_year
{
[Test]
public void if_it_is_not_divisible_by_4(
[Values(2018, 2017, 42, 1)] int year) 
[Test]
public void if_it_is_divisible_by_100_but_not_by_400(
[Values(2100, 1900, 100)] int year) 
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year
{
[Test]
public void if_it_is_divisible_by_4_but_not_by_100(
[Values(2016, 1984, 4)] int year) 
[Test]
public void if_it_is_divisible_by_400(
[Range(400, 2400, 400)] int year) 
}
[TestFixture]
public class A_year_is_not_a_leap_year
{
[Test]
public void if_it_is_not_divisible_by_4(
[Values(2018, 2017, 42, 1)] int year) 
[Test]
public void if_it_is_divisible_by_100_but_not_by_400(
[Values(2100, 1900, 100)] int year) 
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year
{
[Test]
public void is_either_a_leap_year_or_not([Range(1, 10000)] int year) 
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year
{
[Test]
public void is_either_a_leap_year_or_not([Range(1, 10000)] int year) 
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year
{
[Test]
public void is_either_a_leap_year_or_not([Range(1, 10000)] int year)
{
Assert.AreEqual(
year % 4 == 0 && year % 100 != 0 || year % 400 == 0,
IsLeapYear(year));
}
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year
{
[Test]
public void is_either_a_leap_year_or_not([Range(1, 10000)] int year)
{
Assert.AreEqual(LeapYearExpectation(year), IsLeapYear(year));
}
public static bool LeapYearExpectation(int year)
{
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}
}
}
public static bool IsLeapYear(int year)
{
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}
All happy families are alike;
each unhappy family is
unhappy in its own way.
Leo Tolstoy
Anna Karenina
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year 
[TestFixture]
public class A_year_is_not_a_leap_year 
[TestFixture]
public class A_year_is_not_supported
{
[Test]
public void if_it_is_0()
{
Assert.Throws<ArgumentException>(() => IsLeapYear(0));
}
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year 
[TestFixture]
public class A_year_is_not_a_leap_year 
[TestFixture]
public class A_year_is_not_supported
{
[Test]
public void if_it_is_0()
{
Assert.Catch<ArgumentException>(() => IsLeapYear(0));
}
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year 
[TestFixture]
public class A_year_is_not_a_leap_year 
[TestFixture]
public class A_year_is_not_supported
{
[Test]
public void if_it_is_0()
{
Assert.Catch<ArgumentException>(() => IsLeapYear(0));
}
[Test]
public void if_it_is_negative(
[Values(-1, -4, -100, -400)] int year)
{
Assert.Catch<ArgumentException>(() => IsLeapYear(year));
}
}
}
namespace Leap_year_spec
{
[TestFixture]
public class A_year_is_a_leap_year 
[TestFixture]
public class A_year_is_not_a_leap_year 
[TestFixture]
public class A_year_is_supported
{
[Test]
public void if_it_is_positive(
[Values(1, int.MaxValue)] int year)
{
Assert.DoesNotThrow(() => IsLeapYear(year));
}
}
[TestFixture]
public class A_year_is_not_supported 
}
Structure and Interpretation of Test Cases
Stack
{new, push, pop, depth, top}
An abstract data type defines a
class of abstract objects which
is completely characterized by
the operations available on
those objects.
Barbara Liskov
Programming with Abstract Data Types
 T •  Stack
{
new: Stack[T],
push: Stack[T]  T → Stack[T],
pop: Stack[T] ⇸ Stack[T],
depth: Stack[T] → Integer,
top: Stack[T] ⇸ T
}
template<typename T>
class stack
{
public:
stack();
void push(const T & new_top);
void pop();
std::size_t depth() const;
T top() const;
private:
...
};
TEST_CASE(“test stack::stack”) 
TEST_CASE(“test stack::push”) 
TEST_CASE(“test stack::pop”) 
TEST_CASE(“test stack::depth”) 
TEST_CASE(“test stack::top”) 
TEST_CASE(“stack tests”)
{
SECTION(“test constructor”) 
SECTION(“test push”) 
SECTION(“test pop”) 
SECTION(“test depth”) 
SECTION(“test top”) 
}
TEST_CASE(“stack tests”)
{
SECTION(“constructor”) 
SECTION(“push”) 
SECTION(“pop”) 
SECTION(“depth”) 
SECTION(“top”) 
}
template<typename T>
class stack
{
public:
stack();
void push(const T & new_top);
void pop();
std::size_t depth() const;
T top() const;
private:
...
};
template<typename T>
class stack
{
public:
stack() = default;
void push(const T & new_top);
void pop();
std::size_t depth() const;
T top() const;
private:
...
};
TEST_CASE(“stack tests”)
{
SECTION(“constructor”) 
SECTION(“push”) 
SECTION(“pop”) 
SECTION(“depth”) 
SECTION(“top”) 
}
TEST_CASE(“stack tests”)
{
SECTION(“push”) 
SECTION(“pop”) 
SECTION(“depth”) 
SECTION(“top”) 
}
TEST_CASE(“stack tests”)
{
SECTION(“can be constructed”) 
SECTION(“can be pushed”) 
SECTION(“can be popped”) 
SECTION(“has depth”) 
SECTION(“has a top”) 
}
TEST_CASE(“stack tests”)
{
SECTION(“can be constructed”) 
SECTION(“can be pushed”) 
SECTION(“can sometimes be popped”) 
SECTION(“has depth”) 
SECTION(“sometimes has a top”) 
}
https://twitter.com/chrisoldwood/status/918139432447954944
Given
When
Then
an empty stack
an item is pushed
it should not be empty
Given
When
Then
an empty stack
an item is pushed
if it's OK with you, I
think that, perhaps, it
should probably not be
empty, don't you think?
Make definite assertions.
Avoid tame, colourless, hesitating, noncommittal
language.
When a sentence is made stronger, it usually becomes
shorter. Thus brevity is a by-product of vigour.
William Strunk and E B White
The Elements of Style
Given
When
Then
an empty stack
an item is pushed
it must not be empty
Given
When
Then
an empty stack
an item is pushed
it is not empty
Given
When
Then
And
an empty stack
an item is pushed
it has a depth of 1
the top item is the item
that was pushed
GivenAnEmptyStackWhenAnI
temIsPushedThenItHasADep
thOf1AndTheTopItemIsTheI
temThatWasPushed
Given_an_empty_stack_Whe
n_an_item_is_pushed_Then
_it_has_a_depth_of_1_And
_the_top_item_is_the_ite
m_that_was_pushed
Given an empty stack
When an item is pushed
Then it has a depth of 1
And the top item is the
item that was pushed
An empty stack acquires
depth by retaining a
pushed item as its top
Omit needless words.
William Strunk and E B White
The Elements of Style
TEST_CASE(“Stack specification”)
{

SECTION(“An empty stack acquires depth by retaining a pushed item as its top")
{
stack<std::string> stack;
stack.push("ACCU");
REQUIRE(stack.depth() == 1);
REQUIRE(stack.top() == "ACCU");
}

}
TEST_CASE(“Stack specification”)
{
SECTION(“A new stack is empty”) 
SECTION(“An empty stack throws when queried for its top item”) 
SECTION(“An empty stack throws when popped”) 
SECTION(“An empty stack acquires depth by retaining a pushed item as its top”) 
SECTION(“A non-empty stack becomes deeper by retaining a pushed item as its top”) 
SECTION(“A non-empty stack on popping reveals tops in reverse order of pushing”) 
}
TEST_CASE(“Stack specification”)
{
SECTION(“A new stack is empty”) 
SECTION(“An empty stack throws when queried for its top item”) 
SECTION(“An empty stack throws when popped”) 
SECTION(“An empty stack acquires depth by retaining a pushed item as its top”) 
SECTION(“A non-empty stack becomes deeper by retaining a pushed item as its top”) 
SECTION(“A non-empty stack on popping reveals tops in reverse order of pushing”) 
}
TEST_CASE(“Stack specification”)
{

SECTION(“An empty stack acquires depth by retaining a pushed item as its top")
{
stack<std::string> stack;
stack.push("ACCU");
REQUIRE(stack.depth() == 1);
REQUIRE(stack.top() == "ACCU");
}

}
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
TEST_CASE(“Stack specification”)
{

SECTION(“An empty stack acquires depth by retaining a pushed item as its top")
{
// Arrange:
stack<std::string> stack;
// Act:
stack.push("ACCU");
// Assert:
REQUIRE(stack.depth() == 1);
REQUIRE(stack.top() == "ACCU");
}

}
TEST_CASE(“Stack specification”)
{

SECTION(“An empty stack acquires depth by retaining a pushed item as its top")
{
// Arrange:
stack<std::string> stack;
// Act:
stack.push("ACCU");
// Assert:
REQUIRE(stack.depth() == 1);
REQUIRE(stack.top() == "ACCU");
}

}
TEST_CASE(“Stack specification”)
{

SECTION(“An empty stack acquires depth by retaining a pushed item as its top")
{
// Given:
stack<std::string> stack;
// When:
stack.push("ACCU");
// Then:
REQUIRE(stack.depth() == 1);
REQUIRE(stack.top() == "ACCU");
}

}
https://twitter.com/jasongorman/status/572829496342134784
Communications of the ACM, 12(10), October 1969
P {Q} R
If the assertion P is true before
initiation of a program Q, then
the assertion R will be true on
its completion.
{P} Q {R}
Structure and Interpretation of Test Cases
An interface is a contract to deliver a
certain amount of service.
Clients of the interface depend on the
contract, which is usually documented
in the interface specification.
Butler W Lampson
Hints for Computer System Design
template<typename T>
class stack
{
public:
stack();
void push(const T & new_top);
void pop();
std::size_t depth() const;
const T & top() const;
private:
...
};
postcondition:
depth() == 0
where:
old_depth = depth()
postcondition:
depth() == old_depth + 1 && top() == new_top
where:
old_depth = depth()
precondition:
depth() > 0
postcondition:
depth() == old_depth – 1
where:
result = depth()
postcondition:
result >= 0
precondition:
depth() > 0
template<typename T>
class stack
{
public:
stack();
void push(const T & new_top);
void pop();
std::size_t depth() const;
const T & top() const;
private:
...
};
[[expects: depth() == 0]]
[[ensures: depth() > 0]]
[[ensures: top() == new_top]]
[[expects: depth() > 0]]
[[ensures: depth() >= 0]]
[[ensures result: result >= 0]]
[[expects: depth() > 0]]
Structure and Interpretation of Test Cases
alphabet(Stack) =
{new, push, pop, depth, top}
trace(Stack) =
{⟨new⟩,
⟨new, push⟩,
⟨new, depth⟩,
⟨new, push, pop⟩,
⟨new, push, top⟩,
⟨new, push, depth⟩,
⟨new, push, push⟩,
⟨new, depth, push⟩,
⟨new, depth, depth⟩,
⟨new, push, push, pop⟩,
...}
Non-EmptyEmpty
depth depth
top
push
pop [depth > 1]
push
pop [depth = 1]
new
Non-EmptyEmpty
depth
top / error
pop / error
depth
top
push
pop [depth > 1]
push
pop [depth = 1]
new
TEST_CASE("Stack specification")
{
SECTION("A new stack")
{
SECTION("is empty") ...
}
SECTION("An empty stack")
{
SECTION("throws when queried for its top item") ...
SECTION("throws when popped") ...
SECTION("acquires depth by retaining a pushed item as its top") ...
}
SECTION("A non empty stack")
{
SECTION("becomes_deeper_by_retaining_a_pushed_item_as_its_top") ...
SECTION("on popping reveals tops in reverse order of pushing") ...
}
}
TEST_CASE("Stack specification")
{
SECTION("A new stack")
{
SECTION("is empty") ...
}
SECTION("An empty stack")
{
SECTION("throws when queried for its top item") ...
SECTION("throws when popped") ...
SECTION("acquires depth by retaining a pushed item as its top") ...
}
SECTION("A non empty stack")
{
SECTION("becomes_deeper_by_retaining_a_pushed_item_as_its_top") ...
SECTION("on popping reveals tops in reverse order of pushing") ...
}
}
TEST_CASE("Stack specification")
{
SECTION("A new stack")
{
...
}
SECTION("An empty stack")
{
...
SECTION("acquires depth by retaining a pushed item as its top")
{
stack<std::string> stack;
stack.push("ACCU");
REQUIRE(stack.depth() == 1);
REQUIRE(stack.top() == "ACCU");
}
}
SECTION("A non empty stack")
{
...
}
}
TEST_CASE("Stack specification")
{
SECTION("A new stack")
{
...
}
SECTION("An empty stack")
{
stack<std::string> stack;
...
SECTION("acquires depth by retaining a pushed item as its top")
{
stack.push("ACCU");
REQUIRE(stack.depth() == 1);
REQUIRE(stack.top() == "ACCU");
}
}
SECTION("A non empty stack")
{
...
}
}
SCENARIO("Stack specification")
{
...
GIVEN("An empty stack")
{
stack<std::string> stack;
...
WHEN("an item is pushed")
{
stack.push("ACCU");
THEN(“acquires depth by retaining the new item as its top”)
{
REQUIRE(stack.depth() == 1);
REQUIRE(stack.top() == "ACCU");
}
}
}
...
}
SCENARIO("Stack specification")
{
...
GIVEN("An empty stack")
{
stack<std::string> stack;
...
WHEN("an item is pushed")
{
stack.push("ACCU");
THEN(“acquires depth”)
{
REQUIRE(stack.depth() == 1);
}
THEN(“retains the new item as its top”)
{
REQUIRE(stack.top() == "ACCU");
}
}
}
...
}
SCENARIO("Stack specification")
{
...
GIVEN("An empty stack")
{
stack<std::string> stack;
...
WHEN("an item is pushed")
{
stack.push("ACCU");
THEN(“acquires depth”)
REQUIRE(stack.depth() == 1);
THEN(“retains the new item as its top”)
REQUIRE(stack.top() == "ACCU");
}
}
...
}
Given can be used to group
tests for operations with
respect to common
initial state
When can be used to group
tests by operation,
regardless of initial state
or outcome
Then can be used to group
tests by common
outcome, regardless of
operation or initial state
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
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
TEST_CASE("Stack specification")
{
SECTION("A new stack")
{
...
}
SECTION("An empty stack")
{
stack<std::string> stack;
...
SECTION("acquires depth by retaining a pushed item as its top")
{
stack.push("ACCU");
REQUIRE(stack.depth() == 1);
REQUIRE(stack.top() == "ACCU");
}
}
SECTION("A non empty stack")
{
...
}
}
TEST_CASE("Stack specification")
{
SECTION("A new stack")
{
...
}
SECTION("An empty stack")
{
stack<std::string> stack;
...
SECTION("acquires depth by retaining a pushed item as its top")
{
stack.push("ACCU");
REQUIRE(stack.depth() == 1);
REQUIRE(stack.top() == "ACCU");
}
}
SECTION("A non empty stack")
{
...
}
}
TEST_CASE("Stack specification")
{
SECTION("A new stack")
{
...
}
SECTION("An empty stack")
{
stack<std::string> stack;
...
SECTION("acquires depth by retaining a pushed item as its top")
{
stack.push("ACCU");
REQUIRE(stack.items.size() == 1);
REQUIRE(stack.items[0] == "ACCU");
}
}
SECTION("A non empty stack")
{
...
}
}
TEST_CASE("Stack specification")
{
SECTION("A new stack")
{
...
}
SECTION("An empty stack")
{
stack<std::string> stack;
...
SECTION("acquires depth by retaining a pushed item as its top")
{
stack.push("ACCU");
REQUIRE(stack.get_items().size() == 1);
REQUIRE(stack.get_items()[0] == "ACCU");
}
}
SECTION("A non empty stack")
{
...
}
}
TEST_CASE("Stack specification")
{
SECTION("A new stack")
{
...
}
SECTION("An empty stack")
{
stack<std::string> stack;
...
SECTION("acquires depth by retaining a pushed item as its top")
{
stack.push("ACCU");
REQUIRE(stack.items().size() == 1);
REQUIRE(stack.items()[0] == "ACCU");
}
}
SECTION("A non empty stack")
{
...
}
}
TEST_CASE("Stack specification")
{
SECTION("A new stack")
{
...
}
SECTION("An empty stack")
{
stack<std::string> stack;
...
SECTION("acquires depth by retaining a pushed item as its top")
{
stack.push("ACCU");
REQUIRE(stack.depth() == 1);
REQUIRE(stack.top() == "ACCU");
}
}
SECTION("A non empty stack")
{
...
}
}
Structure and Interpretation of Test Cases
A programmer [...] is concerned
only with the behavior which
that object exhibits but not with
any details of how that behavior
is achieved by means of an
implementation.
Barbara Liskov
Programming with Abstract Data Types
template<typename T>
class stack
{
public:
std::size_t depth() const
{
return items.size();
}
const T & top() const
{
if (depth() == 0)
throw std::logic_error("stack has no top");
return items.back();
}
void pop()
{
if (depth() == 0)
throw std::logic_error("cannot pop empty stack");
items.pop_back();
}
void push(const T & new_top)
{
items.push_back(new_top);
}
private:
std::vector<T> items;
};
template<typename T>
class stack
{
public:
std::size_t depth() const
{
return size;
}
const T & top() const
{
if (depth() == 0)
throw std::logic_error("stack has no top");
return items.front();
}
void pop()
{
if (depth() == 0)
throw std::logic_error("cannot pop empty stack");
items.pop_front();
--size;
}
void push(const T & new_top)
{
items.push_front(new_top);
++size;
}
private:
std::size_t size = 0;
std::forward_list<T> items;
};
Structure and Interpretation of Test Cases
Structure and Interpretation of Test Cases
Queue
{new, length, capacity, enqueue, dequeue}
producer consumerspacetime decoupling
N
buffered
bounded
asynchronous
N =
buffered
unbounded
asynchronous
∞
N = 1
buffered
bounded
asynchronous
futurepromise
N = 0
unbuffered
bounded
synchronous
public class Queue<T>
{
...
public Queue(int capacity) ...
public int length() ...
public int capacity() ...
public boolean enqueue(T last) ...
public Optional<T> dequeue() ...
}
Non-EmptyEmpty
length
capacity
dequeue
length
capacity
enqueue
dequeue [length > 1]
enqueue
dequeue [length = 1]
new [capacity > 0]
Non-Full
Empty
length
capacity
dequeue
length
capacity
enqueue
dequeue [length > 1]
enqueue
dequeue [length = 1]
new [capacity > 0]
Full
Non-Empty
[length = capacity]
[length < capacity]
public class Queue_spec 
public class A_new_queue 
public void is_empty() 
public void preserves_positive_bounding_capacity(int capacity) 
public void cannot_be_created_with_non_positive_bounding_capacity(int capacity) 
public class An_empty_queue 
public void dequeues_an_empty_value() 
public void remains_empty_when_null_enqueued() 
public void becomes_non_empty_when_non_null_value_enqueued(String value) 
public class A_non_empty_queue 
public class that_is_not_full 
public void becomes_longer_when_non_null_value_enqueued(String value) 
public void becomes_full_when_enqueued_up_to_capacity() 
public class that_is_full 
public void ignores_further_enqueued_values() 
public void becomes_non_full_when_dequeued() 
public void dequeues_values_in_order_enqueued() 
public void remains_unchanged_when_null_enqueued() 
public class Queue_spec 
public class A_new_queue 
public void is_empty() 
public void preserves_positive_bounding_capacity(int capacity) 
public void cannot_be_created_with_non_positive_bounding_capacity(int capacity) 
public class An_empty_queue 
public void dequeues_an_empty_value() 
public void remains_empty_when_null_enqueued() 
public void becomes_non_empty_when_non_null_value_enqueued(String value) 
public class A_non_empty_queue 
public class that_is_not_full 
public void becomes_longer_when_non_null_value_enqueued(String value) 
public void becomes_full_when_enqueued_up_to_capacity() 
public class that_is_full 
public void ignores_further_enqueued_values() 
public void becomes_non_full_when_dequeued() 
public void dequeues_values_in_order_enqueued() 
public void remains_unchanged_when_null_enqueued() 
public class Queue<T>
{
private Deque<T> items = new LinkedList<>();
private final int capacity;
public Queue(int boundingCapacity)
{
if (boundingCapacity < 1)
throw new IllegalArgumentException();
capacity = boundingCapacity;
}
public int length()
{
return items.size();
}
public int capacity()
{
return capacity;
}
public boolean enqueue(T last)
{
boolean enqueuing = last != null && length() < capacity();
if (enqueuing)
items.addLast(last);
return enqueuing;
}
public Optional<T> dequeue()
{
return Optional.ofNullable(items.pollFirst());
}
}
Structure and Interpretation of Test Cases
Structure and Interpretation of Test Cases

More Related Content

PDF
OWASP Top 10 Web Application Vulnerabilities
PPTX
Password Attack
PPTX
Xss attack
PDF
Understanding Blockchain Security
 
PPTX
Onion protocol
PDF
Blockchain Security Issues and Challenges
PPTX
Blockchain Consensus Protocols
PPTX
Command injection
OWASP Top 10 Web Application Vulnerabilities
Password Attack
Xss attack
Understanding Blockchain Security
 
Onion protocol
Blockchain Security Issues and Challenges
Blockchain Consensus Protocols
Command injection

What's hot (20)

PDF
[KubeCon EU 2022] Running containerd and k3s on macOS
PDF
Understanding Proof of Work (PoW) and Proof of Stake (PoS) Algorithms
PPTX
PPTX
Proxy Presentation
PPTX
Dns server
PDF
Deeper Dive in Docker Overlay Networks
PPTX
PPTX
Unit 1 introduction to web programming
PPSX
Sessions and cookies
PDF
Red Team Methodology - A Naked Look
PDF
macOS Vulnerabilities Hiding in Plain Sight
PDF
DerbyCon 2019 - Kerberoasting Revisited
PPTX
PPT
Networking and penetration testing
PPTX
Migration to ClickHouse. Practical guide, by Alexander Zaitsev
PDF
FIWARE Wednesday Webinars - How to Secure IoT Devices
PPTX
Sql injection
PDF
Web Application Penetration Testing
PPTX
Attacking thru HTTP Host header
PDF
ReCertifying Active Directory
[KubeCon EU 2022] Running containerd and k3s on macOS
Understanding Proof of Work (PoW) and Proof of Stake (PoS) Algorithms
Proxy Presentation
Dns server
Deeper Dive in Docker Overlay Networks
Unit 1 introduction to web programming
Sessions and cookies
Red Team Methodology - A Naked Look
macOS Vulnerabilities Hiding in Plain Sight
DerbyCon 2019 - Kerberoasting Revisited
Networking and penetration testing
Migration to ClickHouse. Practical guide, by Alexander Zaitsev
FIWARE Wednesday Webinars - How to Secure IoT Devices
Sql injection
Web Application Penetration Testing
Attacking thru HTTP Host header
ReCertifying Active Directory
Ad

Similar to Structure and Interpretation of Test Cases (20)

PDF
Program with GUTs
PDF
Programming with GUTs
PDF
C++ Unit Test with Google Testing Framework
PPTX
Junit mockito and PowerMock in Java
PPTX
The real beginner's guide to android testing
PDF
Unit & Automation Testing in Android - Stanislav Gatsev, Melon
PDF
We Are All Testers Now: The Testing Pyramid and Front-End Development
PDF
Test for AI model
PDF
How to write clean tests
PDF
淺談高效撰寫單元測試
PDF
Unit testing with JUnit
PDF
DSR Testing (Part 1)
PPTX
Dev labs alliance top 20 testng interview questions for sdet
PPT
05 junit
PPTX
TestNG vs Junit
ODP
Grails unit testing
PPTX
Tdd is not about testing (OOP)
PDF
AUTOCODECOVERGEN: PROTOTYPE OF DATA DRIVEN UNIT TEST GENRATION TOOL THAT GUAR...
PDF
Hitchhiker's guide to Functional Testing
PDF
Test Driven Development
Program with GUTs
Programming with GUTs
C++ Unit Test with Google Testing Framework
Junit mockito and PowerMock in Java
The real beginner's guide to android testing
Unit & Automation Testing in Android - Stanislav Gatsev, Melon
We Are All Testers Now: The Testing Pyramid and Front-End Development
Test for AI model
How to write clean tests
淺談高效撰寫單元測試
Unit testing with JUnit
DSR Testing (Part 1)
Dev labs alliance top 20 testng interview questions for sdet
05 junit
TestNG vs Junit
Grails unit testing
Tdd is not about testing (OOP)
AUTOCODECOVERGEN: PROTOTYPE OF DATA DRIVEN UNIT TEST GENRATION TOOL THAT GUAR...
Hitchhiker's guide to Functional Testing
Test Driven Development
Ad

More from Kevlin Henney (20)

PDF
The Case for Technical Excellence
PDF
Empirical Development
PDF
Lambda? You Keep Using that Letter
PDF
Lambda? You Keep Using that Letter
PDF
Solid Deconstruction
PDF
Get Kata
PDF
Procedural Programming: It’s Back? It Never Went Away
PDF
Agility ≠ Speed
PDF
Refactoring to Immutability
PDF
Old Is the New New
PDF
Turning Development Outside-In
PDF
Giving Code a Good Name
PDF
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
PDF
Thinking Outside the Synchronisation Quadrant
PDF
Code as Risk
PDF
Software Is Details
PDF
Game of Sprints
PDF
Good Code
PDF
The Error of Our Ways
PDF
Seven Ineffective Coding Habits of Many Programmers
The Case for Technical Excellence
Empirical Development
Lambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
Solid Deconstruction
Get Kata
Procedural Programming: It’s Back? It Never Went Away
Agility ≠ Speed
Refactoring to Immutability
Old Is the New New
Turning Development Outside-In
Giving Code a Good Name
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Thinking Outside the Synchronisation Quadrant
Code as Risk
Software Is Details
Game of Sprints
Good Code
The Error of Our Ways
Seven Ineffective Coding Habits of Many Programmers

Recently uploaded (20)

PPTX
L1 - Introduction to python Backend.pptx
PDF
Nekopoi APK 2025 free lastest update
PPTX
Operating system designcfffgfgggggggvggggggggg
PPTX
ai tools demonstartion for schools and inter college
PPTX
Introduction to Artificial Intelligence
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PPTX
Transform Your Business with a Software ERP System
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PPTX
Reimagine Home Health with the Power of Agentic AI​
PPTX
Essential Infomation Tech presentation.pptx
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
System and Network Administraation Chapter 3
L1 - Introduction to python Backend.pptx
Nekopoi APK 2025 free lastest update
Operating system designcfffgfgggggggvggggggggg
ai tools demonstartion for schools and inter college
Introduction to Artificial Intelligence
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
CHAPTER 2 - PM Management and IT Context
Odoo Companies in India – Driving Business Transformation.pdf
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Transform Your Business with a Software ERP System
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
Reimagine Home Health with the Power of Agentic AI​
Essential Infomation Tech presentation.pptx
Design an Analysis of Algorithms I-SECS-1021-03
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
System and Network Administraation Chapter 3

Structure and Interpretation of Test Cases