2. Outline
1. What is unit testing?
a. what are units?
b. testing the future, TDD
2. Why do we unit test?
a. advantages
i. refactoring
ii. maintainability
3. How do we unit test?
a. Guidelines
b. Assertions
c. Isolations
d. Mocks vs Stubs
4. Related Stuff
3. What is Unit Testing?
Kent Beck introduced the term
legacy code: code without tests
4. What is Unit Testing
Unified Process
Requirements --> Use Cases, Scenarios
Scenarios -> Classes, relationships
classes(or functions in FP) are the units!
Classes -> Unit Tests
5. Why Unit Testing?
To fail when there is no harm to do so
the cost to fix a bug in different stages
did you think about that in advance?
To refactor code (you can still refactor without UT)
To test after development
Self documenting code (if you read them)
6. How to do?
● one test, one scenario
○ no conditional statements like
■ if, switch etc
○ also no loops if possible
■ if there are loops, tests must be broken into other
tests
● one test, one assertion
● isolated test, not depending on each
○ need dependency, use injection, not arbitrary tests
● do not handle exceptions
○ you can assert that an exception will be thrown,
though
● tests are not functions of time!
7. How to do?
when to add tests:
● before new classes/stories
● before fixing new bugs
○ preparing the test scenario
○ filling the gap
● before introducing new features
you can also write tests for the completed code
8. How to do
Unit Test Pattern:
AAA : Arrange - Act - Assert
9. An Example in JUnit
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( {"file:test/test-
config.xml", "file:web/WEB-INF/application-
security.xml",
"file:test/test-dao.xml"} )
public class MobileUtilsTest {
@Autowired
private MobileUtils mobileUtils;
@Autowired
private BankDao bankDao;
10. An Example in JUnit
@Test
public void testGenerateOtp() throws
Exception {
Bank bank = bankDao.findByBin
("402940");
String otp = mobileUtils.generateOtp
(bank);
System.out.println(otp);
Assert.assertNotNull(otp);
}
11. An Example in JUnit
@Test(expected = NullPointerException.class)
public void testGenerateNullBankOtp() throws
Exception{
try{
Bank bank = null;
String otp = mobileUtils.generateOtp
(bank);
}
catch (Exception e){
throw e;
}
}
12. How to do
Assertions:
● use as many as possible different types of
assertions
○ assertThat, assertEquals, assertSame,
assertNotNull
○ junit's matchers
● assertion statements must be readable
○ self documenting tests
○ not assertEquals( result, false )
○ please do assertEquals( result, expectedResult )
13. How to do?
Isolation is important:
● database isolation
○ use a test db if possible
● web container isolation
○ use dependency injection if possible
■ otherwise it is kind of integration testing
● see spring integration testing
● dependency injection
○ provides class isolation
● web services (rest & SOAP)
○ use mocks or stubs
● properties (file and system)
14. How to do?
Automate the tests (otherwise they are
meaningless)
use tools like ant, maven
Better use Jenkins!
15. How to do?
If isolation is important, use mocks and stubs
○ mocks
■ use them when you have dependencies that
cannot be fulfilled by writing simple stubs
● for example, an interface containing many method
declarations
○ stubs
■ use them when you call inner methods to test the
unit, so you don't have to write inner mocks too
16. How to do?
Mocks vs Stubs:
mocks depend on behavior verification
while stubs depend on state verification
examples from Martin Fowler:
17. Stub example
public interface MailService {
public void send (Message msg);
}
public class MailServiceStub implements MailService {
private List<Message> messages = new
ArrayList<Message>();
public void send (Message msg) {
messages.add(msg);
}
public int numberSent() {
return messages.size();
}
}
18. Stub Example
class OrderStateTester...
public void testOrderSendsMailIfUnfilled()
{
Order order = new Order(TALISKER, 51);
MailServiceStub mailer = new
MailServiceStub();
order.setMailer(mailer);
order.fill(warehouse);
assertEquals(1, mailer.numberSent());
}
19. Mock Example
class OrderInteractionTester...
public void testOrderSendsMailIfUnfilled() {
Order order = new Order(TALISKER, 51);
Mock warehouse = mock(Warehouse.class);
Mock mailer = mock(MailService.class);
order.setMailer((MailService) mailer.proxy());
mailer.expects(once()).method("send");
warehouse.expects(once()).method("hasInventory")
.withAnyArguments()
.will(returnValue(false));
order.fill((Warehouse) warehouse.proxy());
//verify
warehouse.verify();
assertTrue(order.isFilled());
}
}
20. Mocks vs Stubs
it really is a decision for TDD
in mocks, you go outside in, one story at a time
usually start from UI
in stubs, you go middle out, also one story,
can begin from business objects
if your code is complete, use real objects,
whenever possible (better code coverage)
21. mockists vs classical
a comparison for TDD
classical tries to use the existing objects in
test
mockist tries to mock complicated stuff and
dependencies
22. For Existing Projects
begin
add tests
submit to vcs
keep tests in a separate folder/module
test both for success and failure
test the important features first
or just write tests at all
end
23. Relatives, Friends
Code coverage
Strive for 100%
For starters, each project must have 20%
remember the 20/80 rule
use tools like http://www.jetbrains.com/idea/features/code_coverage.html
Test Driven Development
basis for TDD, write unit tests first!
can try if you are starting a new project