Anda di halaman 1dari 27

Unit Testing

Hong Trng Th
1
Agenda
Testing vs. verification
What makes code hard to test?
Test Double & Isolation framework
Design for Testability
Unit testing for some specific cases
Equivalence partitioning & boundary data analysis
Code coverage
TDD&BDD
2
Testing or verification
Verification:
Powerful method for finding software errors
Mathematical proof of absence of errors in
implementations relative to specifications
Formal specification and analysis often very
expensive; requires highly qualified engineers
Automated techniques
Model checking & Theorem Proving
(JavaPathFinder, MoonWalker, Spin, CafeOBJ )

Testing:
Can only detect presence of errors
Cannot find all errors
Much cheaper than verification
Requires less mathematical skills
3
Properties of good unit test
Atomic
Deterministic
Repeatable
Order independent & Isolate
Fast
Easy to setup
4
What makes code hard to test?

Code complex

Code that is coupled to other classes

Code that access external resource

GUI

Bad design

Static methods

Global state/singletons

Depend on third party components

Depend on environment (Http Context, File


system)

Behavior testing



5
A common problem with Unit
Testing

6

7
How to solve the dependency?
Test Doubles is a good solution for this
problem
A Test Double is any object or component that
we install in place of the real component
specifically so that we can run a test.
Mock/Isolated framework is the easiest
way for test double
8
Test Doubles
A Dummy Object is a placeholder object
that is passed to the SUT as an argument
but is never actually used.
A Fake Object is an object that replaces
the functionality of the real depended-on
component with an alternate
implementation of the same functionality.
A Test Stub is an object that is used by a
test to replace a real component on which
the SUT depends so that the test can
control the indirect inputs of the SUT.
A Mock Object is an object that is used by
a test to replace a real component on
which the SUT depends so that the test
can verify its indirect outputs.

9
Mocks vs Stubs vs
Dummies vs Fakes
Dummy = passed but not used
Fake = shortcut implementation
Stub = Only pretends to work, returns
pre-defined answer
Mock = Used to test expectations,
requires verification at the end of test

10
Two kinds of unit tests

11
State based testing
Behavior based testing
Stub vs. Mock
Get/Set properties
Set method return values
Test state
Check method calls
Check arguments used
Test behavior
Stub Mock
12
Why engage in Object Mocking?
The real object has behavior that is hard
to cause or is non-deterministic
The real object is difficult to set up
The real object is slow
The real object has (or is ) a UI
Test needs to query the object but queries
are not available
Real objects do not exist
13
Isolation frameworks
Rhino Mocks
Moq
NMock (NMock2)
Typemock Isolator
Moles

14
Best Practice: Design For
Testability
Keep Logic Out Of The UI
Use MVC, MPV, MVVM for UI application
Interfaces
As much as possible, code against interfaces
rather than concrete classes
Makes it easier to create mock objects
Mocks
Lightweight, dummy objects that do exactly
what you want without complex setup
15
Best Practice: Design For
Testability
Avoid using static method/singleton
Avoid using http session, file system
directly
Use dependency injection

16
Coverage

Function coverage, Statement coverage,
Condition/decision coverage, Loop coverage,
Block coverage, Path coverage, Basis Path
Coverage
Code coverage has proven value, but 100%
coverage does not mean no bugs
100% coverage is almost never achieved
Why do we need coverage?
Code coverage helps identify weak test suites
Find out dead code
CFG 1, 2, 3
Cyclomatic complexity = E N + 2P


17
Cyclomatic complexity

18
Cyclomatic complexity
Cyclomatic Complexity Complexity level and Risk
1-10 a simple program, without much risk
11-20 more complex, moderate risk
21-50 more complex, moderate risk
greater than 50 untestable program , very high risk
19
Various researches shown, program module having
CC greater than 10 considered complex. Overly
complex module reduces maintainability and
testability. See below some standard ranges of this
metrics:
Equivalence partitioning &
boundary value analysis
Equivalence Partitioning:
Domain data is divided into different
equivalence partitions
Each partition need a test case
Boundary value analysis:
More errors occur at the boundaries of input
domain. Boundary value analysis testing
technique is used to identify errors at
boundaries rather than finding those exist in
center of input domain.
20
Example
public int Add(int a, int b){
int c = a + b;
if (a >= 0 && b >= 0 && c < 0){
throw new OverflowException("Overfolow!");
}
if (a < 0 && b < 0 && c >= 0){
throw new OverflowException("Underfolow!");
}
return c;
}
21
When do you write the test?
Focus on requirements
Thinking about how code
will be consumed
Stop coding when reqs met
Harder initially
Focus on code
Thinking about algorithm
More refactoring
Easier initially
Before coding (TDD, BDD) After/During coding
22
TDD
23
BDD
24
Story: Returns go to stock

In order to keep track of stock
As a store owner
I want to add items back to stock when they're returned

Scenario 1: Refunded items should be returned to stock
Given a customer previously bought a black sweater from me
And I currently have three black sweaters left in stock
When he returns the sweater for a refund
Then I should have four black sweaters in stock

Scenario 2: Replaced items should be returned to stock
Given that a customer buys a blue garment
And I have two blue garments in stock
And three black garments in stock.
When he returns the garment for a replacement in black,
Then I should have three blue garments in stock
And two black garments in stock
Why Use TDD?
High-quality code with fewer bugs
The bugs you find are easier to diagnose
Using the test first method means you
think out how your code will work ~up-
front design
Less time spent in the debugger
Do you remember what it was like when you first
started doing OO code?
And because you have tests that say when
something works
Easy to maintain & change Refactoring
Code is exercised and the unit tests document how
the developer intended it to be used Self
documenting



25
Q&A
26
Thanks for your attention!
27