Fundamentals of testing by `Testing on the Toilet `
Size: 370.23 KB
Language: en
Added: Feb 20, 2019
Slides: 22 pages
Slide Content
Fundamentals of
testing
What Makes a Good
Test?
clarity
Clarity means that a test should
serve as readable documentation for
humans, describing the code being
tested in terms of its public APIs
completeness and
conciseness
A test is complete when its body contains
all of the information you need to
understand it, and concise when it doesn't
contain any other distracting information.
resilience
Once written, a resilient test
doesn't have to change unless the
purpose or behavior of the class
being tested changes.
Adding new behavior should only
require adding new tests, not
changing old ones. The original test
above isn't resilient since you'll have
to update it (and probably dozens of
other tests!) whenever you add a new
irrelevant constructor parameter.
Moving these details into the helper
method solved this problem.
Test Behaviors, Not
Methods
bad test that verifies an entire method
Displaying the name of the purchased
item and sending an email about the
balance being low are two separate
behaviors, but this test looks at both
of those behaviors together just
because they happen to be triggered
by the same method. Tests like this
very often become massive and
difficult to maintain over time as
additional behaviors keep getting
added in—eventually it will be very
hard to tell which parts of the input
are responsible for which assertions.
The fact that the test's name is a
direct mirror of the method's name is
a bad sign.
use separate tests to verify separate behaviors
Now, when someone adds a new
behavior, they will write a new test for
that behavior. Each test will remain
focused and easy to understand, no
matter how many behaviors are
added. This will make your tests more
resilient since adding new behaviors
is unlikely to break the existing tests,
and clearer since each test contains
code to exercise only one behavior.
Write Descriptive Test
Names
How long does it take you to figure out what behavior is being
tested in the following code?
Make sure test names contain
both the scenario being tested
and the expected outcome
Benefits
•If you want to know all the possible behaviors a class has,
all you need to do is read through the test names in its
test class
•By giving tests more explicit names, it forces you to split
up testing different behaviors into separate tests
•You can easily tell if some functionality isn’t being tested
•When a test fails, you can immediately see what
functionality is broken without looking at the test’s source
code
Benefits
•If you want to know all the possible behaviors a class has,
all you need to do is read through the test names in its
test class
•By giving tests more explicit names, it forces you to split
up testing different behaviors into separate tests
•You can easily tell if some functionality isn’t being tested
•When a test fails, you can immediately see what
functionality is broken without looking at the test’s source
code
Benefits
•If you want to know all the possible behaviors a class has,
all you need to do is read through the test names in its
test class
•By giving tests more explicit names, it forces you to split
up testing different behaviors into separate tests
•You can easily tell if some functionality isn’t being tested
•When a test fails, you can immediately see what
functionality is broken without looking at the test’s source
code
Benefits
•If you want to know all the possible behaviors a class has,
all you need to do is read through the test names in its
test class
•By giving tests more explicit names, it forces you to split
up testing different behaviors into separate tests
•You can easily tell if some functionality isn’t being tested
•When a test fails, you can immediately see what
functionality is broken without looking at the test’s source
code
Benefits
•If you want to know all the possible behaviors a class has,
all you need to do is read through the test names in its
test class
•By giving tests more explicit names, it forces you to split
up testing different behaviors into separate tests
•You can easily tell if some functionality isn’t being tested
•When a test fails, you can immediately see what
functionality is broken without looking at the test’s source
code