SlideShare une entreprise Scribd logo
1  sur  82
Télécharger pour lire hors ligne
SOME
TESTING
Everything you should know about testing
to go with @pedro_g_s, @flipper83 &
@kinisoftware avoiding the hangover
Sergio Arroyo
Software Engineer @
@delr3ves
MOTIVATION
DISCLAIMER
“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 often as we can
the sooner, the better
WHAT ARE WE TALKING ABOUT?
TAXONOMY
Taxonomy	
Scope	
Unit	
Integra3on	
System	
Visibillity	
Black	box	
White	box	
Inten3on	
Acceptance	
Func3onal	
Non	Func3onal	
…	
Technique	
Sta3c	
Dynamic	
Execu3on	
Automa3c	
Manual
Small
Medium
Large
Feature Small Medium Large
Network access No localhost only Yes
Database No Yes Yes
File system access No Yes Yes
Use external systems No Discouraged Yes
Multiple threads No Yes Yes
Sleep statements No Yes Yes
System properties No Yes Yes
Time limit (seconds) 60 300 900+
TESTS BY SCOPE
SCOPE
Database
PORT1 PORT2
ADAPTER1
UNIT TEST
DEPENDENCY INJECTION
➤Dependency:

A depends on B when A needs B to do
its job.
➤Injection:

Object which uses A will tell 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
this sucks
TEST DOUBLES
TEST DOUBLES (FAKE)
Fake implementation in order to make test pass.
public UserDaoFake implements UserDao {
public User create(User user) {
return ...;
}
}
TEST DOUBLES (STUB)
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.
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
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 (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)
Informal: think in a Stub which is also a Spy.
It also responds with default values to non-explicitly declared
methods
UserValidator validatorMock = mock(UserValidator.class);
when(validatorMock.validate(any(User.class)))
.thenTrhow(new ValidationException());
verify(validatorMock).validate(any(User.class))
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
INTEGRATION TEST WHICH WANT TO BE UNIT TESTS
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
INTEGRATION TEST WHICH WORKS WITH EXTERNAL SYSTEM
Database
Fast
Isolates
Repeatable
Self-Validating
Timely
Inmutable*
Trusted*
INTEGRATION TEST WHICH WORKS WITH EXTERNAL SYSTEM
Database
Fast
Isolates
Repeatable
Self-Validating
Timely
Inmutable*
Trusted*
INTEGRATION TEST WHICH USES THE UI
Database
Fast
Isolates
Repeatable
Self-Validating
Timely
Inmutable*
Trusted*
INTEGRATION TEST WHICH USES THE UI
Database
Fast
Isolates
Repeatable
Self-Validating
Timely
Inmutable*
Trusted*
SYSTEM TEST
Database
Fast
Isolates
Repeatable
Self-Validating
Timely
Inmutable*
Trusted*
SYSTEM TEST
Database
Fast
Isolates
Repeatable
Self-Validating
Timely
Inmutable*
Trusted*
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: after commit stage
➤ Where: devel and pre-pro environments
STRATEGIES
STATIC EVALUATION
➤Informal review
➤Formal review (inspection)
➤Checklists
➤Successive 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.
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]))
}
a
b c
d
…x
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]))
}
a
b c
d
…x
edges	–	nodes	+	2	=	predicate	nodes	+1	=	number	of	regions	=	4
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)
Username Password
U1:	myNick P1:	p4ssw0rd
U2:	“empty” P2:	p4ss
P3:	l4rg3p4ssw0rd
P4:	password
Register
Username*
Password	(6-10	chars	including	numbers)
BLACK BOX (PARTITIONING)
Username Password
U1:	myNick P1:	p4ssw0rd
U2:	“empty” P2:	p4ss
P3:	l4rg3p4ssw0rd
P4:	password
Register
Username*
Password	(6-10	chars	including	numbers)
Test	Cases	
	myNick,	p4ssw0rd													√	
	myNick,	p4ss	 																		X	
	myNick,	l4rg3p4ssw0rd				X	
	myNick,	password													X	
	“empty”,	p4ssw0rd											X	
	myNick,	p4sw0rd_*										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*)
➤Constructor does Real Work
➤Mixing business and creation logic
➤Class does too much work
➤Digging into collaborations
➤Brittle Global State & Singletons
*See	hAp://misko.hevery.com/aAachments/Guide-WriIng	Testable	Code.pdf
CONSTRUCTOR 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
SOLID
MIXING BUSINESS AND CREATION LOGIC
➤Use of new inside class methods for a non value object
➤Use of getInstance
SOLID
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 an
quickly “get it”.
➤Class has fields that are only used in some methods.
➤Class has static methods that only operate on parameters.
SOLID
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
SOLID
BRITTLE GLOBAL STATE & SINGLETONS
➤Adding or using singletons.
➤Adding or using static fields or static methods.
➤Adding or using static initialisation blocks.
➤Adding or using registries.
➤Adding or using service locators.
SOLID
TIPS & TRICKS
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?
➤Should I verify every single interaction with my mocks?
➤How do I run my tests?
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>Integra*onTest, …)
➤System tests:
➤Different project
WHERE I PLACE MY TESTS?
Java	Project	(Test	Class	per	Class)	
	MyProject/	
	src/	
					main/	
									java/	
													com.groupId.arIfactId.MyClass.java	
									resources/	
						test/	
										java/	
														com.groupId.arIfactId.MyClassTest.java	
														com.groupId.arIfactId.it.suite.MyTestCaseIntegraIonTest.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.arIfactId.myclass.<SetUp1>Test.java	
													com.groupId.arIfactId.myclass.<SetUp2>Test.java		
													…
WHERE I PLACE MY TESTS?
IOS	Project	
MyIOSProject/	
		MyIOSProject/	
				...	app	code	...	
		MyIOSProjectTests/	
				...	test	code	...	
Android	Project	
	MyProject/	
						AndroidManifest.xml	
						res/	
										...	(resources	for	main	applicaIon)	
						src/	
										main/	
…	(source	code	for	main	applicaIon)	…	
test/	
…	(unit	tests)	…	
androidTest/	
…	(android	specific	tests	/	UI,	etc)	…	
					tests/	
					AndroidManifest.xml	
								res/	
								…	(resources	for	tests)	
								src/	
											...	(source	code	for	tests)
WHO	TESTS	THE	CLASSES	WHICH	TEST	OUR	CLASSES?
➤Exactly, this is why it’s so important our tests follow
KISS
¿COULDYOUBEABLETOREWRITETHECODEONLYREADINGTHETESTSDEFINITIONS?

➤Tests (specially Black Box tests) should tell us an story.
➤Use 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 ...
ISPENDMORETIMEWRITINGCODETOSETUPMYSUTTHANWRITINGTHETEST,HOWDOYOUSOLVEIT?
➤Read about Fixtures (Xunit Patterns is a
good reference).
➤Fresh fixtures
➤Shared fixtures
➤Persistent fixtures
➤Think about new ways of organising your
tests.
IDUPLICATETOOMUCHCODEONOBJECTSCREATION,MOCKSDEFINITIONANDASSERTION…
➤Writing a lot of code to initialize value objects?
➤Create DataBuilders	/	MotherObjects
➤Writing a lot of code to initialize mock/stub objects?
➤Create Mock“Mother”	
➤Writing a lot of asserts (TDD purist	says	only	one	asser<on)?
➤Create CustomAsserts
User user = new User("irrelevantUsername", "v4l1dP4ss",
irrelevant@myCompany.com", ...);
VS
User user = userMother.createValidUser();
assertNotNull(user.getUsername());
assertNotNull(user.getPassword());
assertNotNull(user.getEmail());
...	
VS
assertContainsAllMandatoryData(user);
WHAT	IS	THE	MINIMUM	CODE	COVERAGE?
➤“… 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.
It depends
I’VENEVERWRITEATEST,WHERECANISTART?
I’ll	bet	you	a	beer		
that	you	called	it	
*[Util|Helper]…
Database
PORT1 PORT2
ADAPTER1
MYCODEISNOTTESTABLEATALL,WHATCANIDO?
➤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
REMOVES NEW FOR DEPENDENCIES
public UserService() {	
this(new UserValidator(), new UserDao());
}
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;
}
TO
REMOVE STATIC CLASSES AND METHODS
class MyJsonSerializer {
public static String serialize(Object myObject) {
//put your magic here	
}
}
class UserClient {
public void createUser(User user) {
Http.post(url, JsonSerizalizer.serialize(user));
}
}
REMOVE STATIC CLASSES AND METHODS
class MysonSerializer {
public String serialize(Object myObject) {
//put your magic here	
}
}
class HttpClientWrapper {
public void post(String url, String body) {
Http.post(url, body);
}
}
class UserClient {
private JsonSerializer serializer;
private HttpClientWrapper httpClient
public UserClient() {
serializer = new JsonSerializer();
httpClient = new HttpClientWrapper();
}	
public void createUser(User user) {
httpClient.post(url, serializer.serialize(user));
}
}
SHOULD I VERIFY EVERY SINGLE INTERACTION WITH MY MOCKS?
It depends
HOW DO I RUN MY TESTS?
➤ Java / Android
➤$ mvn test
➤$ gradle test
➤ Ruby
➤$ rake test
➤PHP
➤$ phpunit <testFolder/File>
➤ NodeJs
➤$ npm test
➤$ grunt test
➤ Javascript (client)
➤$ karma star
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/
➤…
Q&A
Place	your	question	here!
@delr3ves

Contenu connexe

Tendances

Tendances (20)

Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
 
Testing in-groovy
Testing in-groovyTesting in-groovy
Testing in-groovy
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
Effective Unit Testing
Effective Unit TestingEffective Unit Testing
Effective Unit Testing
 
Advance unittest
Advance unittestAdvance unittest
Advance unittest
 
JUnit Pioneer
JUnit PioneerJUnit Pioneer
JUnit Pioneer
 
Java Programming - 03 java control flow
Java Programming - 03 java control flowJava Programming - 03 java control flow
Java Programming - 03 java control flow
 
Grails Spock Testing
Grails Spock TestingGrails Spock Testing
Grails Spock Testing
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for Programmers
 
Unit test-using-spock in Grails
Unit test-using-spock in GrailsUnit test-using-spock in Grails
Unit test-using-spock in Grails
 
JUnit & Mockito, first steps
JUnit & Mockito, first stepsJUnit & Mockito, first steps
JUnit & Mockito, first steps
 
Java language fundamentals
Java language fundamentalsJava language fundamentals
Java language fundamentals
 
Java Inheritance
Java InheritanceJava Inheritance
Java Inheritance
 
Mock your way with Mockito
Mock your way with MockitoMock your way with Mockito
Mock your way with Mockito
 
Exceptions
ExceptionsExceptions
Exceptions
 
Android testing
Android testingAndroid testing
Android testing
 
GMock framework
GMock frameworkGMock framework
GMock framework
 
10 Typical Enterprise Java Problems
10 Typical Enterprise Java Problems10 Typical Enterprise Java Problems
10 Typical Enterprise Java Problems
 
JMockit Framework Overview
JMockit Framework OverviewJMockit Framework Overview
JMockit Framework Overview
 
Basic Unit Testing with Mockito
Basic Unit Testing with MockitoBasic Unit Testing with Mockito
Basic Unit Testing with Mockito
 

Similaire à Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover

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
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
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
 
J unit presentation
J unit presentationJ unit presentation
J unit presentationPriya Sharma
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good TestsTomek Kaczanowski
 
Security Testing
Security TestingSecurity Testing
Security TestingKiran Kumar
 
An introduction to unit testing
An introduction to unit testingAn introduction to unit testing
An introduction to unit testingAdam Stephensen
 
Unit testing php-unit - phing - selenium_v2
Unit testing   php-unit - phing - selenium_v2Unit testing   php-unit - phing - selenium_v2
Unit testing php-unit - phing - selenium_v2Tricode (part of Dept)
 
Building unit tests correctly
Building unit tests correctlyBuilding unit tests correctly
Building unit tests correctlyDror Helper
 
Testing basics for developers
Testing basics for developersTesting basics for developers
Testing basics for developersAnton Udovychenko
 
Unit Testing in PHP
Unit Testing in PHPUnit Testing in PHP
Unit Testing in PHPRadu Murzea
 
Unit Testing on Android - Droidcon Berlin 2015
Unit Testing on Android - Droidcon Berlin 2015Unit Testing on Android - Droidcon Berlin 2015
Unit Testing on Android - Droidcon Berlin 2015Buşra Deniz, CSM
 
Testing And Drupal
Testing And DrupalTesting And Drupal
Testing And DrupalPeter Arato
 

Similaire à Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover (20)

Unit Testing
Unit TestingUnit Testing
Unit Testing
 
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
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit 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
 
Introduzione al TDD
Introduzione al TDDIntroduzione al TDD
Introduzione al TDD
 
J unit presentation
J unit presentationJ unit presentation
J unit presentation
 
JUnit Presentation
JUnit PresentationJUnit Presentation
JUnit Presentation
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
Test driven development
Test driven developmentTest driven development
Test driven development
 
Security Testing
Security TestingSecurity Testing
Security Testing
 
An introduction to unit testing
An introduction to unit testingAn introduction to unit testing
An introduction to unit testing
 
Unit testing php-unit - phing - selenium_v2
Unit testing   php-unit - phing - selenium_v2Unit testing   php-unit - phing - selenium_v2
Unit testing php-unit - phing - selenium_v2
 
Building unit tests correctly
Building unit tests correctlyBuilding unit tests correctly
Building unit tests correctly
 
Testing basics for developers
Testing basics for developersTesting basics for developers
Testing basics for developers
 
Unit Testing in PHP
Unit Testing in PHPUnit Testing in PHP
Unit Testing in PHP
 
Unit Testing on Android - Droidcon Berlin 2015
Unit Testing on Android - Droidcon Berlin 2015Unit Testing on Android - Droidcon Berlin 2015
Unit Testing on Android - Droidcon Berlin 2015
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Testing And Drupal
Testing And DrupalTesting And Drupal
Testing And Drupal
 
8-testing.pptx
8-testing.pptx8-testing.pptx
8-testing.pptx
 

Dernier

Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceanilsa9823
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
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
 
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
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
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
 

Dernier (20)

Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
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
 
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
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
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
 

Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover

  • 1. SOME TESTING Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover
  • 5. “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
  • 10. WHAT ARE WE TALKING ABOUT?
  • 11.
  • 14.
  • 16. Feature Small Medium Large Network access No localhost only Yes Database No Yes Yes File system access No Yes Yes Use external systems No Discouraged Yes Multiple threads No Yes Yes Sleep statements No Yes Yes System properties No Yes Yes Time limit (seconds) 60 300 900+
  • 20. DEPENDENCY INJECTION ➤Dependency:
 A depends on B when A needs B to do its job. ➤Injection:
 Object which uses A will tell A who is B.
  • 21. 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.
  • 22. 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
  • 23. 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 this sucks
  • 25. TEST DOUBLES (FAKE) Fake implementation in order to make test pass. public UserDaoFake implements UserDao { public User create(User user) { return ...; } }
  • 26. TEST DOUBLES (STUB) 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. 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
  • 27. 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();
  • 28. 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();
  • 29. TEST DOUBLES (MOCKS) Informal: think in a Stub which is also a Spy. It also responds with default values to non-explicitly declared methods UserValidator validatorMock = mock(UserValidator.class); when(validatorMock.validate(any(User.class))) .thenTrhow(new ValidationException()); verify(validatorMock).validate(any(User.class)) 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
  • 30. INTEGRATION TEST WHICH WANT TO BE UNIT TESTS
  • 31. 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
  • 32. INTEGRATION TEST WHICH WORKS WITH EXTERNAL SYSTEM Database Fast Isolates Repeatable Self-Validating Timely Inmutable* Trusted*
  • 33. INTEGRATION TEST WHICH WORKS WITH EXTERNAL SYSTEM Database Fast Isolates Repeatable Self-Validating Timely Inmutable* Trusted*
  • 34. INTEGRATION TEST WHICH USES THE UI Database Fast Isolates Repeatable Self-Validating Timely Inmutable* Trusted*
  • 35. INTEGRATION TEST WHICH USES THE UI Database Fast Isolates Repeatable Self-Validating Timely Inmutable* Trusted*
  • 38. 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: after commit stage ➤ Where: devel and pre-pro environments
  • 40. STATIC EVALUATION ➤Informal review ➤Formal review (inspection) ➤Checklists ➤Successive abstraction ➤Walkthrough
  • 41. DYNAMIC EVALUATION ➤White box ➤Path Coverage ➤Statement Coverage ➤Condition Coverage ➤Function Coverage ➤Black box ➤Equivalence partitioning ➤Boundary values analysis
  • 42. 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])) }
  • 43. 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])) } a b c d …x
  • 44. 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])) } a b c d …x edges – nodes + 2 = predicate nodes +1 = number of regions = 4
  • 45. 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
  • 47. BLACK BOX (PARTITIONING) Username Password U1: myNick P1: p4ssw0rd U2: “empty” P2: p4ss P3: l4rg3p4ssw0rd P4: password Register Username* Password (6-10 chars including numbers)
  • 48. BLACK BOX (PARTITIONING) Username Password U1: myNick P1: p4ssw0rd U2: “empty” P2: p4ss P3: l4rg3p4ssw0rd P4: password Register Username* Password (6-10 chars including numbers) Test Cases myNick, p4ssw0rd √ myNick, p4ss X myNick, l4rg3p4ssw0rd X myNick, password X “empty”, p4ssw0rd X myNick, p4sw0rd_* X
  • 50. 4 PHASES-TESTS 1. Set Up 2. Exercise 3. Verify 4. TearDown
  • 51. 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
  • 52. 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 }
  • 53. 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:
  • 54. 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 }) }) })
  • 55. 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 |
  • 56. 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) { ... }
  • 58. NON-TESTABLE DESIGN SMELLS (BY MISKO HEVERY*) ➤Constructor does Real Work ➤Mixing business and creation logic ➤Class does too much work ➤Digging into collaborations ➤Brittle Global State & Singletons *See hAp://misko.hevery.com/aAachments/Guide-WriIng Testable Code.pdf
  • 59. CONSTRUCTOR 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 SOLID
  • 60. MIXING BUSINESS AND CREATION LOGIC ➤Use of new inside class methods for a non value object ➤Use of getInstance SOLID
  • 61. 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 an quickly “get it”. ➤Class has fields that are only used in some methods. ➤Class has static methods that only operate on parameters. SOLID
  • 62. 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 SOLID
  • 63. BRITTLE GLOBAL STATE & SINGLETONS ➤Adding or using singletons. ➤Adding or using static fields or static methods. ➤Adding or using static initialisation blocks. ➤Adding or using registries. ➤Adding or using service locators. SOLID
  • 65. 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? ➤Should I verify every single interaction with my mocks? ➤How do I run my tests?
  • 66. 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>Integra*onTest, …) ➤System tests: ➤Different project
  • 67. WHERE I PLACE MY TESTS? Java Project (Test Class per Class) MyProject/ src/ main/ java/ com.groupId.arIfactId.MyClass.java resources/ test/ java/ com.groupId.arIfactId.MyClassTest.java com.groupId.arIfactId.it.suite.MyTestCaseIntegraIonTest.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.arIfactId.myclass.<SetUp1>Test.java com.groupId.arIfactId.myclass.<SetUp2>Test.java …
  • 68. WHERE I PLACE MY TESTS? IOS Project MyIOSProject/ MyIOSProject/ ... app code ... MyIOSProjectTests/ ... test code ... Android Project MyProject/ AndroidManifest.xml res/ ... (resources for main applicaIon) src/ main/ … (source code for main applicaIon) … test/ … (unit tests) … androidTest/ … (android specific tests / UI, etc) … tests/ AndroidManifest.xml res/ … (resources for tests) src/ ... (source code for tests)
  • 69. WHO TESTS THE CLASSES WHICH TEST OUR CLASSES? ➤Exactly, this is why it’s so important our tests follow KISS
  • 70. ¿COULDYOUBEABLETOREWRITETHECODEONLYREADINGTHETESTSDEFINITIONS?
 ➤Tests (specially Black Box tests) should tell us an story. ➤Use 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 ...
  • 71. ISPENDMORETIMEWRITINGCODETOSETUPMYSUTTHANWRITINGTHETEST,HOWDOYOUSOLVEIT? ➤Read about Fixtures (Xunit Patterns is a good reference). ➤Fresh fixtures ➤Shared fixtures ➤Persistent fixtures ➤Think about new ways of organising your tests.
  • 72. IDUPLICATETOOMUCHCODEONOBJECTSCREATION,MOCKSDEFINITIONANDASSERTION… ➤Writing a lot of code to initialize value objects? ➤Create DataBuilders / MotherObjects ➤Writing a lot of code to initialize mock/stub objects? ➤Create Mock“Mother” ➤Writing a lot of asserts (TDD purist says only one asser<on)? ➤Create CustomAsserts User user = new User("irrelevantUsername", "v4l1dP4ss", irrelevant@myCompany.com", ...); VS User user = userMother.createValidUser(); assertNotNull(user.getUsername()); assertNotNull(user.getPassword()); assertNotNull(user.getEmail()); ... VS assertContainsAllMandatoryData(user);
  • 73. WHAT IS THE MINIMUM CODE COVERAGE? ➤“… 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. It depends
  • 75. MYCODEISNOTTESTABLEATALL,WHATCANIDO? ➤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
  • 76. REMOVES NEW FOR DEPENDENCIES public UserService() { this(new UserValidator(), new UserDao()); } 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; } TO
  • 77. REMOVE STATIC CLASSES AND METHODS class MyJsonSerializer { public static String serialize(Object myObject) { //put your magic here } } class UserClient { public void createUser(User user) { Http.post(url, JsonSerizalizer.serialize(user)); } }
  • 78. REMOVE STATIC CLASSES AND METHODS class MysonSerializer { public String serialize(Object myObject) { //put your magic here } } class HttpClientWrapper { public void post(String url, String body) { Http.post(url, body); } } class UserClient { private JsonSerializer serializer; private HttpClientWrapper httpClient public UserClient() { serializer = new JsonSerializer(); httpClient = new HttpClientWrapper(); } public void createUser(User user) { httpClient.post(url, serializer.serialize(user)); } }
  • 79. SHOULD I VERIFY EVERY SINGLE INTERACTION WITH MY MOCKS? It depends
  • 80. HOW DO I RUN MY TESTS? ➤ Java / Android ➤$ mvn test ➤$ gradle test ➤ Ruby ➤$ rake test ➤PHP ➤$ phpunit <testFolder/File> ➤ NodeJs ➤$ npm test ➤$ grunt test ➤ Javascript (client) ➤$ karma star
  • 81. 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/ ➤…