SlideShare uma empresa Scribd logo
1 de 66
Testing
A brief introduction
Main concepts
“I get paid for code that works, not for
tests, so my philosophy is to test as little
as possible to reach a given level of
confidence …”
Kent Beck
No silver bullets
What is testing about?
Getting feedback,
as much frequent as we can
the sooner, the better
TAXONOMY
Taxonomy
Scope
Unit
Integration
System
Visibillity
Black box
White box
Intention
Acceptance
Functional
Non Functional
…
Technique
Static
Dynamic
Execution
Automatic
Manual
Visibillity
Black
box
White
box
System
Integration
Unit
Intention
Acceptance
Functional
Non
Functional
Technique
Dynamic
Static
Scope
Database
PORT1 PORT2
ADAPTER1
Unittest
Database
Dependency injection
•Dependency:
A depends on B when A needs B to do
its job.
•Injection:
Object which uses A tells A who is B.
Dependency injection
• Separate business logic from creation logic
• Avoid use of new for service objects.
• Value objects can be created any where.
• Service objects in charge to implement business
logic.
• IOC Container or factories in charge of creation
logic.
Dependency injection
public UserService(UserValidator userValidator, UserDao userDao) {
this.userValidator = userValidator;
this.userDao = userDao;
}
public User createUser(User user) throws ValidationException {
this.userValidator.validate(user);
user = this.userDao.create(user);
return user;
}
public User createUser(User user) throws ValidationException {
UserValidator userValidator = new UserValidator(...);
userValidator.validate(user);
UserDao userDao = new UserDao(...);
user = userDao.create(user);
return user;
}
VS
Dependency injection
public UserService(UserValidator userValidator, UserDao userDao) {
this.userValidator = userValidator;
this.userDao = userDao;
}
public User createUser(User user) throws ValidationException {
this.userValidator.validate(user);
user = this.userDao.create(user);
return user;
}
public User createUser(User user) throws ValidationException {
UserValidator userValidator = new UserValidator(...);
userValidator.validate(user);
UserDao userDao = new UserDao(...);
user = userDao.create(user);
return user;
}
VS
Test doubles
•Fake
•Stub
•Spy
•Mock
Test doubles (Fake)
public UserDaoFake implements UserDao {
@Override
public User create(User user) {
return new User(...);
}
}
Fake implementation in order to make test pass.
Test doubles (Stub)
UserValidator validatorMock = mock(UserValidator.class);
stub(validatorMock.validate(any(User.class))).toThrow(new ValidationException());
var validateCall = Sinon.stub();
validatorStub.withArgs(user)
.onFirstCall().returns(validationError);
var userValidator = {
validate: validatorStub;
}
OR WITH JS
Stubs provide canned answers to calls made during the test,
usually not responding at all to anything outside what’s
programmed in for the test.
Test doubles (Spy)
Spies are objects that also record some
information based on how they were called
var validatorSpy = Sinon.spy();
var userValidator = {
validate: validatorSpy;
}
userValidator.validate(user);
sinon.assert.calledOnce(validatorSpy);
sinon.assert.calledWith(validatorSpy, user);
OR WITH JS
UserValidator validatorSpy = spy(new UserValidator());
doThrow(new ValidationException()).when(validatorSpy).validate();
verify(validatorMock).validate(any(User.class))
Test doubles (Spy)
Spies are objects that also record some
information based on how they were called
var validatorSpy = Sinon.spy();
var userValidator = {
validate: validatorSpy;
}
userValidator.validate(user);
sinon.assert.calledOnce(validatorSpy);
sinon.assert.calledWith(validatorSpy, user);
OR WITH JS
UserValidator validatorSpy = spy(new UserValidator());
doThrow(new ValidationException()).when(validatorSpy).validate();
Test doubles (Mocks)
UserValidator validatorMock = mock(UserValidator.class);
when(validatorMock.validate(any(User.class))).thenTrhow(new ValidationException());
verify(validatorMock).validate(any(User.class))
Informal: think in a Stub which is also a Spy.
It also responds with default values to non-explicitly
declared methods
var validatorAPI = {validate: function()};
var validatorMock = Sinon.mock(validatorAPI);
validatorMock.expects('validate').once()
.withArgs(user).throws(validationError)
validatorAPI.validate(user)
validatorMock.verify()
OR WITH JS
Integrationtestwhichwanttobeunittests
Database
FIRST(IT)
• Fast
Hundreds or thousands per second
• Isolates
Failure reasons become obvious
• Repeatable
In any order, any time
• Self-validating
No manual execution required
• Timely
Written before code
• Immutable*
SUT is in the same state after execute the tests
• Trusted*
When the test fails, the system fail and when the test works, the system
works
Integrationtestwhichworkswithexternalsystem
Database
IntegrationtestwhichusestheUI
Database
Systemtest
Database
Who, when and where run the tests?
• Unit
• Owner: developer
• When: after every change
• Where: every computer
• Integration
• Owner: developer || QA team
• When: as part or after commit stage
• Where: devel and pre-pro environments
• System
• Owner: QA team
• When: as part or after commit stage
• Where: devel and pre-pro environments
STRATEGIES
Static evaluation
•Informal review
•Formal review (inspection)
• Checklists
• Sucessive abstraction
•Walkthrough
Dynamic evaluation
• White box
• Path Coverage
• Statement Coverage
• Condition Coverage
• Function Coverage
• Black box
• Equivalence partitioning
• Boundary values analysis
White box (*-coverage)
1. Get flow diagram of the SUT
2. Calculate cyclomatic complexity
3. Determine a data set which force going one path or another
4. Exercise the SUT with this dataset.
...
errors = []
if (user.name ==null || user.email == null) {
errors.push('mandatory fields not found');
}
//do the rest of whatever
for (var i=0; i < user.friends ; i++) {
errors.push(checkFriendShipt(user.friends[i]))
}
...
White box (*-coverage)
1. Get flow diagram of the SUT
2. Calculate cyclomatic complexity
3. Determine a data set which force going one path or another
4. Exercise the SUT with this dataset.
a
b c
d
…x
...
errors = []
if (user.name ==null || user.email == null) {
errors.push('mandatory fields not found');
}
//do the rest of whatever
for (var i=0; i < user.friends ; i++) {
errors.push(checkFriendShipt(user.friends[i]))
}
...
White box (*-coverage)
1. Get flow diagram of the SUT
2. Calculate cyclomatic complexity
3. Determine a data set which force going one path or another
4. Exercise the SUT with this dataset.
edges – nodes + 2 = predicate nodes +1 = number of regions
a
b c
d
…x
...
errors = []
if (user.name ==null || user.email == null) {
errors.push('mandatory fields not found');
}
//do the rest of whatever
for (var i=0; i < user.friends ; i++) {
errors.push(checkFriendShipt(user.friends[i]))
}
...
Black box (partitioning)
1. Identify equivalence classes
2. Select dataset:
1. Assign a unique value for every class
2. Select tests cases which cover the most
valid classes
3. Select tests cases which cover only one
invalid class at the same time
Black box (partitioning)
Register
Username*
Password (6-10 chars including numbers)
Black box (partitioning)
Register
Username*
Password (6-10 chars including numbers)
Username Password
U1: myNick P1: p4ssw0rd
U2: “empty” P2: p4ss
P3: l4rg3p4ssw0rd
P4: password
Black box (partitioning)
Register
Username*
Password (6-10 chars including numbers)
Username Password
U1: myNick P1: p4ssw0rd
U2: “empty” P2: p4ss
P3: l4rg3p4ssw0rd
P4: password
Test Cases
myNick, p4ssw0rd √
myNick, p4ss X
myNick, l4rg3p4ssw0rd X
myNick, password X
“empty”, p4ssw0rd X
AUTOMATIC TESTING
4 phases-tests
1.Set Up
2.Exercise
3.Verify
4.TearDown
Testing frameworks families
• X-Unit
• @Before(Class)
• @Test
• @After(Class)
• Rspec
• describe
• beforeEach
• it
• afterEach
• Specification by example (A.K.A BDD)
• Given
• When
• Then
XUnit
@Before
public void setUp() {
this.userValidator = mock(UserValidator.class);
this.userDao = mock(UserDao.class);
this.userService = new UserService(userValidator, userDao);
}
@Test
public void createValidUserShouldNotFail() {
//Exercise
User expectedCreatedUser = new User("irrelevantUser");
when(userValidator.validate(any(User.class)));
when(userValidator.validate(any(User.class))).thenReturn(createdUser);
User createdUser = userService.create(new User());
//Assertions
assertThat(createdUser, equalTo(expectedCreatedUser));
}
@Test(expected=ValidationException)
public void createInvalidUserShouldFail() {
when(userValidator.validate(any(User.class)))
.thenReturn(new ValidationException());
userService.create(new User("irrelevantUser"));
}
@After
public void tearDown() {
//clean the state here
}
Rspec (suite per class)
describe('UserService test suite:', function(){
beforeEach(function(){
// setup the SUT
})
it('when create a valid user should not fail', function(){
// exercise + assertions
})
it('when create an invalid user should fail', function(){
// exercise + assertions
})
afterEach(function(){
// clean the state
})
})
• UserService test suite:
• When create a valid user should not fail √
• When create an invalid user should fail √
The report will look like:
Rspec (suite per setup)
describe('UserService test suite:', function(){
describe("when create a valid user ", function() {
beforeEach(function(){
// setup and exercise
})
it('should return valid user', function(){
// partial assertions
})
it('should call validator', function(){
// partial assertions
})
it('should call dao', function(){
// partial assertions
})
afterEach(function(){
// clean the state
})
})
})
BDD (specification)
Feature: User registration
Scenario: User tries to register sending valid data so the system will create new account
Given the user has introduced <username> and <password> into the registration form
And has accepted terms and agreements
When send the registration from
Then the user with <username> should be created
Example:
| username | password |
| myNick | p4ssw0rd |
Scenario: User tries to register sending invalid data so the system will reject user
Given the user has introduced <username> and <password> into the registration form
And has accepted terms and agreements
When send the registration from
Then the system should notify <error>
Example:
| username | password | error |
| myNick | p4ss | password should have at least 6 characters |
| myNick | l4rg3p4ssword | password should have at less than 10 characters |
| myNick | password | password should contains at least a number |
| | p4ssword | username is mandatory |
BDD(implementation)
@given("the user has introduced (w)+ and (w)+ into the registration form")
public void populateForm(String username, String password) {
...
}
@given("has accepted terms and agreements")
public void acceptTerms() {
...
}
@when("send the registration from")
public void sendRegistrationForm() {
...
}
@then("the user with (w)+ should be created")
public void verifyUserIsCreated(String username) {
...
}
@then("the system should notify <error>")
public void verifyErrors(String error) {
...
}
TESTABLE DESIGN
Non-Testable design smells
(by Misko Hevery*)
•Constructors does Real Work
•Digging into collaborators
•Brittle Global State & Singletons
•Class Does Too Much Work
*See http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf
Constructors does Real Work
• new keyword in a constructor or at field declaration
• Static method calls in a constructor or at field declaration
• Anything more than field assignment in constructors
• Object not fully initialized after the constructor finishes
(watch out for initialize methods)
• Control flow (conditional or looping logic) in a
constructor
• CL does complex object graph construction inside a
constructor rather than using a factory or builder
• Adding or using an initialization block
Digging into collaborators
• Objects are passed in but never used directly
(only used to get access to other objects)
• Law of Demeter violation: method call chain
walks an object graph with more than one dot (.)
• Suspicious names: context, environment,
principal, container, or manager
Brittle Global State & Singletons
• Adding or using singletons
• Adding or using static fields or static
methods
• Adding or using static initialization blocks
• Adding or using registries
• Adding or using service locators
Class Does Too Much Work
• Summing up what the class does includes the
word “and”
• Class would be challenging for new team
members to read and quickly “get it”
• Class has fields that are only used in some
methods
• Class has static methods that only operate on
parameters
Questions & Stupid questions
• ¿Where I place my tests?
• ¿Who tests the classes which test our classes?
• ¿Could you be able to rewrite the code only reading the tests
definitions?
• I spend more time writing code to setup my SUT than writing
the test, how do you solve it?
• ¿What is the minimum coverage should I expect for my code?
• I’ve never write a test ¿where can I start?
• My code is not testable at all, ¿what can I do?
¿Where I place my tests?
• Unit tests:
• Test Class per Class
• Test Class per SetUp (useful in Xunit frameworks)
• Important naming convention (<ClassName>Test,
<TestSuite>IntegrationTest, …)
• System tests:
• Different project
¿Where I place my tests?
Java Project (Test Class per Class)
MyProject/
src/
main/
java/
com.groupId.artifactId.MyClass.java
resources/
test/
java/
com.groupId.artifactId.MyClassTest.java
com.groupId.artifactId.it.suite.MyTestCaseIntegrationTest.java
resources/
NodeJs Project
MyProject/
lib/
myClass.js
main.js
test/
ut/
/suite
it/
lib/
myClassTest.js
Java Project (Class per SetUp)
MyProject/
src/
main/
…
test/
java/
com.groupId.artifactId.myclass.<SetUp1>Test.java
com.groupId.artifactId.myclass.<SetUp2>Test.java
…
¿Where I place my tests?
Android Project
MyProject/
AndroidManifest.xml
res/
... (resources for main application)
src/
... (source code for main application) ...
tests/
AndroidManifest.xml
res/
... (resources for tests)
src/
... (source code for tests)
IOS Project
MyIOSProject/
MyIOSProject/
... app code ...
MyIOSProjectTests/
... test code ...
¿Who tests the classes which
test our classes?
• Exactly, this is why it’s so important our tests follow
KISS
¿Couldyoube able to rewrite the codeonly
reading the tests definitions?
• Tests (specially Black Box tests) should tell us an story.
• Use descriptive name methods for unit tests:
• User well defined, and complete scenarios for system tests:
• Use business vocabulary for acceptance tests:
public void testValidaterUser1 { ... }
VS
public void validateUserWithNoPasswordShouldThrowsError { ... }
com.mycompany.artifactId.it.TestSteps ...
VS
com.mycompany.artifactId.it.usermanagement.UserCreationSteps ...
IspendmoretimewritingcodetosetupmySUTthan
writingthetest,howdo you solveit?
• Read about Fixtures (Xunit Patterns is a
good reference)
• Fresh fixtures
• Shared fixtures
• Persistent fixtures
Iduplicatetoomuchcodeonobjectscreation,mocks
definitionandassertion…
• Writing a lot of code to initialize value objects?
• Create DataBuilders
• Writing a lot of code to initialize mock/stub objects?
• Create MockBuilders
• Writing a lot of asserts (more purist says only one assertion)?
• Create CustomAsserts
User user = userDataBuilder.createValidUser();
VS
User user = new User("irrelevantUsername", "v4l1dP4ss", irrelevant@myCompany.com", ...);
assertNotNull(user.getUsername());
assertNotNull(user.getPassword());
assertNotNull(user.getEmail());
...
VS
assertContainsAllMandatoryData(user);
¿What is the minimum coverage
should I expect for my code?
• It depends on the project.
• “… test as little as possible to reach a given level
of confidence …”
• Do not get obsess over test coverage, it’s a
metric, not a goal.
I’ve never write a test ¿where can I
start?
Database
PORT1 PORT2
ADAPTER1
I’ll bet you a
beer , you
called it *Util…
My code is not testable at all,
¿what can I do?
• First of all, go to http://refactoring.com/
• I suggest:
1. Add integration regression test.
2. Remove new from methods and ad it to constructors (this will
prepare your class for dependency injection).
3. Creates a constructor which receive every dependency your
class will need.
4. Remove static classes and methods (adding the new non-static
as a class dependency).
5. Add as much tests as you want to ;)
Important!!! Do it step by step
Recommended reading
• Growing Object Oriented Software Guided Tests
• Xunit Patterns
• Continuous delivery
• Hexagonal Architecture
• Inversion of Control Container and the Dependency Injection
pattern
• Mocks aren’t Stubs
• Misko Hevery blog
• http://refactoring.com/
• …
Place your question here!

Mais conteúdo relacionado

Mais procurados

Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with MockitoRichard Paul
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for ProgrammersDavid Rodenas
 
JUnit & Mockito, first steps
JUnit & Mockito, first stepsJUnit & Mockito, first steps
JUnit & Mockito, first stepsRenato Primavera
 
Android testing
Android testingAndroid testing
Android testingSean Tsai
 
Basic Unit Testing with Mockito
Basic Unit Testing with MockitoBasic Unit Testing with Mockito
Basic Unit Testing with MockitoAlexander De Leon
 
JMockit Framework Overview
JMockit Framework OverviewJMockit Framework Overview
JMockit Framework OverviewMario Peshev
 
JUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJohn Ferguson Smart Limited
 
10 Typical Enterprise Java Problems
10 Typical Enterprise Java Problems10 Typical Enterprise Java Problems
10 Typical Enterprise Java ProblemsEberhard Wolff
 
Testing And Mxunit In ColdFusion
Testing And Mxunit In ColdFusionTesting And Mxunit In ColdFusion
Testing And Mxunit In ColdFusionDenard Springle IV
 
Mockito with a hint of PowerMock
Mockito with a hint of PowerMockMockito with a hint of PowerMock
Mockito with a hint of PowerMockYing Zhang
 
Mockito a simple, intuitive mocking framework
Mockito   a simple, intuitive mocking frameworkMockito   a simple, intuitive mocking framework
Mockito a simple, intuitive mocking frameworkPhat VU
 
xUnit Style Database Testing
xUnit Style Database TestingxUnit Style Database Testing
xUnit Style Database TestingChris Oldwood
 
關於測試,我說的其實是......
關於測試,我說的其實是......關於測試,我說的其實是......
關於測試,我說的其實是......hugo lu
 

Mais procurados (20)

Testing in-groovy
Testing in-groovyTesting in-groovy
Testing in-groovy
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
 
JUnit Pioneer
JUnit PioneerJUnit Pioneer
JUnit Pioneer
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for Programmers
 
JUnit & Mockito, first steps
JUnit & Mockito, first stepsJUnit & Mockito, first steps
JUnit & Mockito, first steps
 
Mock your way with Mockito
Mock your way with MockitoMock your way with Mockito
Mock your way with Mockito
 
Android testing
Android testingAndroid testing
Android testing
 
Mockito intro
Mockito introMockito intro
Mockito intro
 
Basic Unit Testing with Mockito
Basic Unit Testing with MockitoBasic Unit Testing with Mockito
Basic Unit Testing with Mockito
 
Migrating to JUnit 5
Migrating to JUnit 5Migrating to JUnit 5
Migrating to JUnit 5
 
JMockit Framework Overview
JMockit Framework OverviewJMockit Framework Overview
JMockit Framework Overview
 
JUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit Tests
 
Exceptions
ExceptionsExceptions
Exceptions
 
10 Typical Enterprise Java Problems
10 Typical Enterprise Java Problems10 Typical Enterprise Java Problems
10 Typical Enterprise Java Problems
 
Testing And Mxunit In ColdFusion
Testing And Mxunit In ColdFusionTesting And Mxunit In ColdFusion
Testing And Mxunit In ColdFusion
 
Mockito with a hint of PowerMock
Mockito with a hint of PowerMockMockito with a hint of PowerMock
Mockito with a hint of PowerMock
 
Mockito a simple, intuitive mocking framework
Mockito   a simple, intuitive mocking frameworkMockito   a simple, intuitive mocking framework
Mockito a simple, intuitive mocking framework
 
Java Threads
Java ThreadsJava Threads
Java Threads
 
xUnit Style Database Testing
xUnit Style Database TestingxUnit Style Database Testing
xUnit Style Database Testing
 
關於測試,我說的其實是......
關於測試,我說的其實是......關於測試,我說的其實是......
關於測試,我說的其實是......
 

Semelhante a Introduction to Software Testing

MT_01_unittest_python.pdf
MT_01_unittest_python.pdfMT_01_unittest_python.pdf
MT_01_unittest_python.pdfHans Jones
 
Security Testing
Security TestingSecurity Testing
Security TestingKiran Kumar
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014FalafelSoftware
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
Pragmatic unittestingwithj unit
Pragmatic unittestingwithj unitPragmatic unittestingwithj unit
Pragmatic unittestingwithj unitliminescence
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testingpleeps
 
Java Unit Test and Coverage Introduction
Java Unit Test and Coverage IntroductionJava Unit Test and Coverage Introduction
Java Unit Test and Coverage IntroductionAlex Su
 
Testing the waters of iOS
Testing the waters of iOSTesting the waters of iOS
Testing the waters of iOSKremizas Kostas
 
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)Jen Wong
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentAll Things Open
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Dror Helper
 
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdfLECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdfShashikantSathe3
 
saihw1_weka_tutorial.pptx - Machine Discovery and Social Network ...
saihw1_weka_tutorial.pptx - Machine Discovery and Social Network ...saihw1_weka_tutorial.pptx - Machine Discovery and Social Network ...
saihw1_weka_tutorial.pptx - Machine Discovery and Social Network ...butest
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxDavid Rodenas
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
Principles and patterns for test driven development
Principles and patterns for test driven developmentPrinciples and patterns for test driven development
Principles and patterns for test driven developmentStephen Fuqua
 

Semelhante a Introduction to Software Testing (20)

MT_01_unittest_python.pdf
MT_01_unittest_python.pdfMT_01_unittest_python.pdf
MT_01_unittest_python.pdf
 
Test driven development
Test driven developmentTest driven development
Test driven development
 
Introduzione al TDD
Introduzione al TDDIntroduzione al TDD
Introduzione al TDD
 
Security Testing
Security TestingSecurity Testing
Security Testing
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Pragmatic unittestingwithj unit
Pragmatic unittestingwithj unitPragmatic unittestingwithj unit
Pragmatic unittestingwithj unit
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
Qtp day 3
Qtp day 3Qtp day 3
Qtp day 3
 
Java Unit Test and Coverage Introduction
Java Unit Test and Coverage IntroductionJava Unit Test and Coverage Introduction
Java Unit Test and Coverage Introduction
 
Testing the waters of iOS
Testing the waters of iOSTesting the waters of iOS
Testing the waters of iOS
 
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013
 
Effective Unit Testing
Effective Unit TestingEffective Unit Testing
Effective Unit Testing
 
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdfLECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
LECTURE 2 MORE TYPES, METHODS, CONDITIONALS.pdf
 
saihw1_weka_tutorial.pptx - Machine Discovery and Social Network ...
saihw1_weka_tutorial.pptx - Machine Discovery and Social Network ...saihw1_weka_tutorial.pptx - Machine Discovery and Social Network ...
saihw1_weka_tutorial.pptx - Machine Discovery and Social Network ...
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Principles and patterns for test driven development
Principles and patterns for test driven developmentPrinciples and patterns for test driven development
Principles and patterns for test driven development
 

Último

Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Intelisync
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
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
 
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
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
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
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
(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
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
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
 
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
 

Último (20)

Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
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
 
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...
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
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
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
(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...
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
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...
 
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
 

Introduction to Software Testing

  • 3. “I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence …” Kent Beck
  • 6. Getting feedback, as much frequent as we can
  • 11.
  • 14. Dependency injection •Dependency: A depends on B when A needs B to do its job. •Injection: Object which uses A tells A who is B.
  • 15. Dependency injection • Separate business logic from creation logic • Avoid use of new for service objects. • Value objects can be created any where. • Service objects in charge to implement business logic. • IOC Container or factories in charge of creation logic.
  • 16. Dependency injection public UserService(UserValidator userValidator, UserDao userDao) { this.userValidator = userValidator; this.userDao = userDao; } public User createUser(User user) throws ValidationException { this.userValidator.validate(user); user = this.userDao.create(user); return user; } public User createUser(User user) throws ValidationException { UserValidator userValidator = new UserValidator(...); userValidator.validate(user); UserDao userDao = new UserDao(...); user = userDao.create(user); return user; } VS
  • 17. Dependency injection public UserService(UserValidator userValidator, UserDao userDao) { this.userValidator = userValidator; this.userDao = userDao; } public User createUser(User user) throws ValidationException { this.userValidator.validate(user); user = this.userDao.create(user); return user; } public User createUser(User user) throws ValidationException { UserValidator userValidator = new UserValidator(...); userValidator.validate(user); UserDao userDao = new UserDao(...); user = userDao.create(user); return user; } VS
  • 19. Test doubles (Fake) public UserDaoFake implements UserDao { @Override public User create(User user) { return new User(...); } } Fake implementation in order to make test pass.
  • 20. Test doubles (Stub) UserValidator validatorMock = mock(UserValidator.class); stub(validatorMock.validate(any(User.class))).toThrow(new ValidationException()); var validateCall = Sinon.stub(); validatorStub.withArgs(user) .onFirstCall().returns(validationError); var userValidator = { validate: validatorStub; } OR WITH JS Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what’s programmed in for the test.
  • 21. Test doubles (Spy) Spies are objects that also record some information based on how they were called var validatorSpy = Sinon.spy(); var userValidator = { validate: validatorSpy; } userValidator.validate(user); sinon.assert.calledOnce(validatorSpy); sinon.assert.calledWith(validatorSpy, user); OR WITH JS UserValidator validatorSpy = spy(new UserValidator()); doThrow(new ValidationException()).when(validatorSpy).validate(); verify(validatorMock).validate(any(User.class))
  • 22. Test doubles (Spy) Spies are objects that also record some information based on how they were called var validatorSpy = Sinon.spy(); var userValidator = { validate: validatorSpy; } userValidator.validate(user); sinon.assert.calledOnce(validatorSpy); sinon.assert.calledWith(validatorSpy, user); OR WITH JS UserValidator validatorSpy = spy(new UserValidator()); doThrow(new ValidationException()).when(validatorSpy).validate();
  • 23. Test doubles (Mocks) UserValidator validatorMock = mock(UserValidator.class); when(validatorMock.validate(any(User.class))).thenTrhow(new ValidationException()); verify(validatorMock).validate(any(User.class)) Informal: think in a Stub which is also a Spy. It also responds with default values to non-explicitly declared methods var validatorAPI = {validate: function()}; var validatorMock = Sinon.mock(validatorAPI); validatorMock.expects('validate').once() .withArgs(user).throws(validationError) validatorAPI.validate(user) validatorMock.verify() OR WITH JS
  • 25. FIRST(IT) • Fast Hundreds or thousands per second • Isolates Failure reasons become obvious • Repeatable In any order, any time • Self-validating No manual execution required • Timely Written before code • Immutable* SUT is in the same state after execute the tests • Trusted* When the test fails, the system fail and when the test works, the system works
  • 29. Who, when and where run the tests? • Unit • Owner: developer • When: after every change • Where: every computer • Integration • Owner: developer || QA team • When: as part or after commit stage • Where: devel and pre-pro environments • System • Owner: QA team • When: as part or after commit stage • Where: devel and pre-pro environments
  • 31. Static evaluation •Informal review •Formal review (inspection) • Checklists • Sucessive abstraction •Walkthrough
  • 32. Dynamic evaluation • White box • Path Coverage • Statement Coverage • Condition Coverage • Function Coverage • Black box • Equivalence partitioning • Boundary values analysis
  • 33. White box (*-coverage) 1. Get flow diagram of the SUT 2. Calculate cyclomatic complexity 3. Determine a data set which force going one path or another 4. Exercise the SUT with this dataset. ... errors = [] if (user.name ==null || user.email == null) { errors.push('mandatory fields not found'); } //do the rest of whatever for (var i=0; i < user.friends ; i++) { errors.push(checkFriendShipt(user.friends[i])) } ...
  • 34. White box (*-coverage) 1. Get flow diagram of the SUT 2. Calculate cyclomatic complexity 3. Determine a data set which force going one path or another 4. Exercise the SUT with this dataset. a b c d …x ... errors = [] if (user.name ==null || user.email == null) { errors.push('mandatory fields not found'); } //do the rest of whatever for (var i=0; i < user.friends ; i++) { errors.push(checkFriendShipt(user.friends[i])) } ...
  • 35. White box (*-coverage) 1. Get flow diagram of the SUT 2. Calculate cyclomatic complexity 3. Determine a data set which force going one path or another 4. Exercise the SUT with this dataset. edges – nodes + 2 = predicate nodes +1 = number of regions a b c d …x ... errors = [] if (user.name ==null || user.email == null) { errors.push('mandatory fields not found'); } //do the rest of whatever for (var i=0; i < user.friends ; i++) { errors.push(checkFriendShipt(user.friends[i])) } ...
  • 36. Black box (partitioning) 1. Identify equivalence classes 2. Select dataset: 1. Assign a unique value for every class 2. Select tests cases which cover the most valid classes 3. Select tests cases which cover only one invalid class at the same time
  • 38. Black box (partitioning) Register Username* Password (6-10 chars including numbers) Username Password U1: myNick P1: p4ssw0rd U2: “empty” P2: p4ss P3: l4rg3p4ssw0rd P4: password
  • 39. Black box (partitioning) Register Username* Password (6-10 chars including numbers) Username Password U1: myNick P1: p4ssw0rd U2: “empty” P2: p4ss P3: l4rg3p4ssw0rd P4: password Test Cases myNick, p4ssw0rd √ myNick, p4ss X myNick, l4rg3p4ssw0rd X myNick, password X “empty”, p4ssw0rd X
  • 42. Testing frameworks families • X-Unit • @Before(Class) • @Test • @After(Class) • Rspec • describe • beforeEach • it • afterEach • Specification by example (A.K.A BDD) • Given • When • Then
  • 43. XUnit @Before public void setUp() { this.userValidator = mock(UserValidator.class); this.userDao = mock(UserDao.class); this.userService = new UserService(userValidator, userDao); } @Test public void createValidUserShouldNotFail() { //Exercise User expectedCreatedUser = new User("irrelevantUser"); when(userValidator.validate(any(User.class))); when(userValidator.validate(any(User.class))).thenReturn(createdUser); User createdUser = userService.create(new User()); //Assertions assertThat(createdUser, equalTo(expectedCreatedUser)); } @Test(expected=ValidationException) public void createInvalidUserShouldFail() { when(userValidator.validate(any(User.class))) .thenReturn(new ValidationException()); userService.create(new User("irrelevantUser")); } @After public void tearDown() { //clean the state here }
  • 44. Rspec (suite per class) describe('UserService test suite:', function(){ beforeEach(function(){ // setup the SUT }) it('when create a valid user should not fail', function(){ // exercise + assertions }) it('when create an invalid user should fail', function(){ // exercise + assertions }) afterEach(function(){ // clean the state }) }) • UserService test suite: • When create a valid user should not fail √ • When create an invalid user should fail √ The report will look like:
  • 45. Rspec (suite per setup) describe('UserService test suite:', function(){ describe("when create a valid user ", function() { beforeEach(function(){ // setup and exercise }) it('should return valid user', function(){ // partial assertions }) it('should call validator', function(){ // partial assertions }) it('should call dao', function(){ // partial assertions }) afterEach(function(){ // clean the state }) }) })
  • 46. BDD (specification) Feature: User registration Scenario: User tries to register sending valid data so the system will create new account Given the user has introduced <username> and <password> into the registration form And has accepted terms and agreements When send the registration from Then the user with <username> should be created Example: | username | password | | myNick | p4ssw0rd | Scenario: User tries to register sending invalid data so the system will reject user Given the user has introduced <username> and <password> into the registration form And has accepted terms and agreements When send the registration from Then the system should notify <error> Example: | username | password | error | | myNick | p4ss | password should have at least 6 characters | | myNick | l4rg3p4ssword | password should have at less than 10 characters | | myNick | password | password should contains at least a number | | | p4ssword | username is mandatory |
  • 47. BDD(implementation) @given("the user has introduced (w)+ and (w)+ into the registration form") public void populateForm(String username, String password) { ... } @given("has accepted terms and agreements") public void acceptTerms() { ... } @when("send the registration from") public void sendRegistrationForm() { ... } @then("the user with (w)+ should be created") public void verifyUserIsCreated(String username) { ... } @then("the system should notify <error>") public void verifyErrors(String error) { ... }
  • 49. Non-Testable design smells (by Misko Hevery*) •Constructors does Real Work •Digging into collaborators •Brittle Global State & Singletons •Class Does Too Much Work *See http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf
  • 50. Constructors does Real Work • new keyword in a constructor or at field declaration • Static method calls in a constructor or at field declaration • Anything more than field assignment in constructors • Object not fully initialized after the constructor finishes (watch out for initialize methods) • Control flow (conditional or looping logic) in a constructor • CL does complex object graph construction inside a constructor rather than using a factory or builder • Adding or using an initialization block
  • 51. Digging into collaborators • Objects are passed in but never used directly (only used to get access to other objects) • Law of Demeter violation: method call chain walks an object graph with more than one dot (.) • Suspicious names: context, environment, principal, container, or manager
  • 52. Brittle Global State & Singletons • Adding or using singletons • Adding or using static fields or static methods • Adding or using static initialization blocks • Adding or using registries • Adding or using service locators
  • 53. Class Does Too Much Work • Summing up what the class does includes the word “and” • Class would be challenging for new team members to read and quickly “get it” • Class has fields that are only used in some methods • Class has static methods that only operate on parameters
  • 54. Questions & Stupid questions • ¿Where I place my tests? • ¿Who tests the classes which test our classes? • ¿Could you be able to rewrite the code only reading the tests definitions? • I spend more time writing code to setup my SUT than writing the test, how do you solve it? • ¿What is the minimum coverage should I expect for my code? • I’ve never write a test ¿where can I start? • My code is not testable at all, ¿what can I do?
  • 55. ¿Where I place my tests? • Unit tests: • Test Class per Class • Test Class per SetUp (useful in Xunit frameworks) • Important naming convention (<ClassName>Test, <TestSuite>IntegrationTest, …) • System tests: • Different project
  • 56. ¿Where I place my tests? Java Project (Test Class per Class) MyProject/ src/ main/ java/ com.groupId.artifactId.MyClass.java resources/ test/ java/ com.groupId.artifactId.MyClassTest.java com.groupId.artifactId.it.suite.MyTestCaseIntegrationTest.java resources/ NodeJs Project MyProject/ lib/ myClass.js main.js test/ ut/ /suite it/ lib/ myClassTest.js Java Project (Class per SetUp) MyProject/ src/ main/ … test/ java/ com.groupId.artifactId.myclass.<SetUp1>Test.java com.groupId.artifactId.myclass.<SetUp2>Test.java …
  • 57. ¿Where I place my tests? Android Project MyProject/ AndroidManifest.xml res/ ... (resources for main application) src/ ... (source code for main application) ... tests/ AndroidManifest.xml res/ ... (resources for tests) src/ ... (source code for tests) IOS Project MyIOSProject/ MyIOSProject/ ... app code ... MyIOSProjectTests/ ... test code ...
  • 58. ¿Who tests the classes which test our classes? • Exactly, this is why it’s so important our tests follow KISS
  • 59. ¿Couldyoube able to rewrite the codeonly reading the tests definitions? • Tests (specially Black Box tests) should tell us an story. • Use descriptive name methods for unit tests: • User well defined, and complete scenarios for system tests: • Use business vocabulary for acceptance tests: public void testValidaterUser1 { ... } VS public void validateUserWithNoPasswordShouldThrowsError { ... } com.mycompany.artifactId.it.TestSteps ... VS com.mycompany.artifactId.it.usermanagement.UserCreationSteps ...
  • 60. IspendmoretimewritingcodetosetupmySUTthan writingthetest,howdo you solveit? • Read about Fixtures (Xunit Patterns is a good reference) • Fresh fixtures • Shared fixtures • Persistent fixtures
  • 61. Iduplicatetoomuchcodeonobjectscreation,mocks definitionandassertion… • Writing a lot of code to initialize value objects? • Create DataBuilders • Writing a lot of code to initialize mock/stub objects? • Create MockBuilders • Writing a lot of asserts (more purist says only one assertion)? • Create CustomAsserts User user = userDataBuilder.createValidUser(); VS User user = new User("irrelevantUsername", "v4l1dP4ss", irrelevant@myCompany.com", ...); assertNotNull(user.getUsername()); assertNotNull(user.getPassword()); assertNotNull(user.getEmail()); ... VS assertContainsAllMandatoryData(user);
  • 62. ¿What is the minimum coverage should I expect for my code? • It depends on the project. • “… test as little as possible to reach a given level of confidence …” • Do not get obsess over test coverage, it’s a metric, not a goal.
  • 63. I’ve never write a test ¿where can I start? Database PORT1 PORT2 ADAPTER1 I’ll bet you a beer , you called it *Util…
  • 64. My code is not testable at all, ¿what can I do? • First of all, go to http://refactoring.com/ • I suggest: 1. Add integration regression test. 2. Remove new from methods and ad it to constructors (this will prepare your class for dependency injection). 3. Creates a constructor which receive every dependency your class will need. 4. Remove static classes and methods (adding the new non-static as a class dependency). 5. Add as much tests as you want to ;) Important!!! Do it step by step
  • 65. Recommended reading • Growing Object Oriented Software Guided Tests • Xunit Patterns • Continuous delivery • Hexagonal Architecture • Inversion of Control Container and the Dependency Injection pattern • Mocks aren’t Stubs • Misko Hevery blog • http://refactoring.com/ • …