#codemotion2016: everything you should know about testing to go with @pedro_g_s, @flipper83 &...
TRANSCRIPT
![Page 1: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/1.jpg)
SOME TESTING
The miseries and great hardships of software testingSergio Arroyo Cuevas - @delr3ves
![Page 2: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/2.jpg)
“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
![Page 3: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/3.jpg)
WHO AM I?
![Page 4: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/4.jpg)
WHO AM I?
![Page 5: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/5.jpg)
MOTIVATION
![Page 6: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/6.jpg)
DISCLAIMER
![Page 7: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/7.jpg)
No silver bullets
![Page 8: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/8.jpg)
What is testing about?
![Page 9: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/9.jpg)
Getting feedback,as often as we can
![Page 10: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/10.jpg)
the sooner, the better
![Page 11: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/11.jpg)
So please, send me your’s@delr3ves
![Page 12: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/12.jpg)
WHAT ARE WE TALKING ABOUT?
![Page 13: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/13.jpg)
![Page 14: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/14.jpg)
TAXONOMY
![Page 15: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/15.jpg)
Taxono
my
Scope
Unit
Integra3on
System
VisibillityBlackbox
Whitebox
Inten3on
Acceptance
Func3onal
NonFunc3onal
…
TechniqueSta3c
Dynamic
Execu3onAutoma3c
Manual
Google’s
Small
Medium
Big
![Page 16: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/16.jpg)
![Page 17: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/17.jpg)
TESTS BY SCOPE
![Page 18: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/18.jpg)
SCOPE
Database
PORT1 PORT2
ADAPTER1
![Page 19: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/19.jpg)
UNIT TEST
![Page 20: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/20.jpg)
DEPENDENCY INJECTION
➤Dependency:A depends on B when A needs B to do its job.
➤Injection:Object (C) which uses A will tell A who is B.
![Page 21: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/21.jpg)
DEPENDENCY INJECTION
➤Dependency:A depends on B when A needs B to do its job.
➤Injection: Object (C) which uses A will tell A who is B.
![Page 22: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/22.jpg)
DEPENDENCY INJECTION
CA
B
➤A depends on B ➤C will tell A who is C
![Page 23: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/23.jpg)
![Page 24: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/24.jpg)
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.
![Page 25: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/25.jpg)
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
![Page 26: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/26.jpg)
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; }
VSthis sucks
![Page 27: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/27.jpg)
TEST DOUBLES
![Page 28: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/28.jpg)
TEST DOUBLES (FAKE)
Fake implementation in order to make test pass.
public UserDaoFake implements UserDao {
public User create(User user) { return ...; } }
![Page 29: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/29.jpg)
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
![Page 30: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/30.jpg)
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();
![Page 31: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/31.jpg)
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();
![Page 32: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/32.jpg)
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
![Page 33: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/33.jpg)
INTEGRATION TEST WHICH WANT TO BE UNIT TESTS
![Page 34: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/34.jpg)
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
![Page 35: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/35.jpg)
INTEGRATION TEST WHICH WORKS WITH EXTERNAL SYSTEM
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 36: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/36.jpg)
INTEGRATION TEST WHICH WORKS WITH EXTERNAL SYSTEM
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 37: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/37.jpg)
INTEGRATION TEST WHICH USES THE UI
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 38: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/38.jpg)
INTEGRATION TEST WHICH USES THE UI
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 39: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/39.jpg)
SYSTEM TEST
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 40: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/40.jpg)
SYSTEM TEST
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 41: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/41.jpg)
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
![Page 42: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/42.jpg)
STRATEGIES
![Page 43: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/43.jpg)
STATIC EVALUATION
➤Informal review ➤Formal review (inspection) ➤Checklists ➤Successive abstraction
➤Walkthrough
![Page 44: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/44.jpg)
DYNAMIC EVALUATION
➤White box ➤Path Coverage ➤Statement Coverage ➤Condition Coverage ➤Function Coverage
➤Black box ➤Equivalence partitioning ➤Boundary values analysis
![Page 45: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/45.jpg)
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]))
}
![Page 46: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/46.jpg)
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
![Page 47: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/47.jpg)
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
![Page 48: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/48.jpg)
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
![Page 49: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/49.jpg)
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
![Page 50: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/50.jpg)
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
![Page 51: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/51.jpg)
BLACK BOX (PARTITIONING)
Register
Username*
Password (6-10 chars including numbers)
![Page 52: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/52.jpg)
BLACK BOX (PARTITIONING)
Username Password
U1: myNick P1: p4ssw0rdU2: “empty” P2: p4ss
P3: l4rg3p4ssw0rdP4: password
Register
Username*
Password (6-10 chars including numbers)
![Page 53: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/53.jpg)
BLACK BOX (PARTITIONING)
Username Password
U1: myNick P1: p4ssw0rdU2: “empty” P2: p4ss
P3: l4rg3p4ssw0rdP4: 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
![Page 54: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/54.jpg)
BLACK BOX (METHODS WHICH TELL US A STORY)
VS
![Page 55: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/55.jpg)
BLACK BOX (METHODS WHICH TELL US A STORY)
but if you hate exceptions…
![Page 56: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/56.jpg)
AUTOMATIC TESTING
![Page 57: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/57.jpg)
4 PHASES-TESTS
1. Set Up 2. Exercise 3. Verify 4. TearDown
![Page 58: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/58.jpg)
TESTING FRAMEWORKS FAMILIES
➤X-Unit ➤@Before(Class)
➤@Test
➤@After(Class)
➤Spec ➤describe
➤ beforeEach
➤ it
➤ afterEach
➤Specification by example (A.K.A BDD) ➤Given
➤When
➤Then
![Page 59: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/59.jpg)
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}
![Page 60: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/60.jpg)
SPEC (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:
![Page 61: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/61.jpg)
SPEC (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 }) }) })
![Page 62: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/62.jpg)
BDD (SPECIFICATION)
Feature: User registrationScenario: 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 createdExample: | 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 |
![Page 63: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/63.jpg)
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) { ... }
![Page 64: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/64.jpg)
TESTABLE DESIGN
![Page 65: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/65.jpg)
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 http://misko.hevery.com/attachments/Guide-Writing Testable Code.pdf
![Page 66: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/66.jpg)
FROM NON-TESTABLE TO TESTABLE
➤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. Add a factory for Stateful services
4. Creates a constructor which receive every dependency your class will need.
5. Remove static classes and methods (adding the new non-static as a class dependency).
6. Add as much tests as you want to ;)
➤Important!!! Do it step by step
![Page 67: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/67.jpg)
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
![Page 68: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/68.jpg)
ADD FACTORIES FOR STATEFUL DEPENDENCIES
public UserService() { this(new UserValidatorFactory(), new UserDao()); } public UserService(UserValidator userValidatorFactory, UserDao userDao) { this.userValidatorFactory = userValidatorFactory; this.userDao = userDao; }
public User createUser(User user) throws ValidationException { this.userValidatorFactory.getInstance(user).validate(); ... }
public User createUser(User user) throws ValidationException { UserValidator userValidator = new UserValidator(user); userValidator.validate(); ... }
TO
![Page 69: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/69.jpg)
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)); } }
![Page 70: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/70.jpg)
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)); } }
![Page 71: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/71.jpg)
TIPS & TRICKS
![Page 72: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/72.jpg)
QUESTIONS & STUPID QUESTIONS
➤I spend more time writing code to setup my SUT than writing the test, how do you solve it?
➤I’ve never write a test, where can I start?
➤Should I verify every single interaction with my mocks?
➤Who tests the classes which test our classes?
➤Where I place my tests?
➤Could you be able to rewrite the code only reading the tests definitions?
➤What is the minimum coverage should I expect for my code?
![Page 73: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/73.jpg)
I SPEND MORE TIME WRITING CODE TO SETUP MY SUT THAN WRITING THE TEST, HOW DO YOU SOLVE IT?
➤Read about Fixtures (Xunit Patterns is a good reference). ➤Fresh fixtures
➤Shared fixtures
➤Persistent fixtures ➤Think about new ways of organising your
tests.
![Page 74: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/74.jpg)
I DUPLICATE TOO MUCH CODE ON OBJECTS CREATION, MOCKS DEFINITION AND ASSERTION…
➤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 assertion)? ➤Create CustomAsserts
User user = new User("irrelevantUsername", "v4l1dP4ss", [email protected]", ...);
VS User user = userMother.createValidUser();
assertNotNull(user.getUsername()); assertNotNull(user.getPassword()); assertNotNull(user.getEmail());
...VS
assertContainsAllMandatoryData(user);
![Page 75: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/75.jpg)
I’VE NEVER WRITE A TEST, WHERE CAN I START?
I’ll bet you a beer that you called it *[Util|Helper]…
Database
PORT1 PORT2
ADAPTER1
![Page 76: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/76.jpg)
SHOULD I VERIFY EVERY SINGLE INTERACTION WITH MY MOCKS?
It depends But if you feel you have to, it’s probably due
to a bad design :S
![Page 77: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/77.jpg)
WHO TESTS THE CLASSES WHICH TEST OUR CLASSES?
➤Exactly, this is why it’s so important our tests follow
KISS
![Page 78: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/78.jpg)
Q&APlace your question here!
@delr3ves
![Page 79: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/79.jpg)
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
![Page 80: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/80.jpg)
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 …
![Page 81: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/81.jpg)
WHERE I PLACE MY TESTS?
IOS ProjectMyIOSProject/ MyIOSProject/ ... app code ... MyIOSProjectTests/ ... test code ...
Android Project MyProject/ AndroidManifest.xml res/ ... (resources for main application) src/ main/
… (source code for main application) …test/
… (unit tests) …androidTest/
… (android specific tests / UI, etc) … tests/
AndroidManifest.xml res/
… (resources for tests) src/ ... (source code for tests)
![Page 82: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/82.jpg)
¿COULD YOU BE ABLE TO REWRITE THE CODE ONLY READING THE TESTS DEFINITIONS?
➤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 validate_user_with_no_password_should_throws_error { ... }
com.mycompany.artifactId.it.TestSteps ...
VS
com.mycompany.artifactId.it.usermanagement.UserCreationSteps ...
![Page 83: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/83.jpg)
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
![Page 84: #codemotion2016: Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader030.vdocuments.net/reader030/viewer/2022032806/588535461a28ab26518b5c7d/html5/thumbnails/84.jpg)
Q&APlace your question here!
@delr3ves