some testing - everything you should know about testing to go with @pedro_g_s, @flipper83 &...
TRANSCRIPT
![Page 1: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/1.jpg)
SOME TESTING
Everything you should know about testing to go with @pedro_g_s, @flipper83 &
@kinisoftware avoiding the hangover
![Page 2: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/2.jpg)
Sergio Arroyo
Software Engineer @
@delr3ves
![Page 3: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/3.jpg)
MOTIVATION
![Page 4: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/4.jpg)
DISCLAIMER
![Page 5: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/5.jpg)
“I get paid for code thatworks, not for tests, somyphilosophy is to test as little as possible to reach agivenlevelofconfidence…
-Kent Beck
![Page 6: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/6.jpg)
No silver bullets
![Page 7: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/7.jpg)
What is testing about?
![Page 8: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/8.jpg)
Getting feedback,as often as we can
![Page 9: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/9.jpg)
the sooner, the better
![Page 10: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/10.jpg)
WHAT ARE WE TALKING ABOUT?
![Page 11: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/11.jpg)
![Page 12: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/12.jpg)
TAXONOMY
![Page 13: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/13.jpg)
Taxono
my
Scope
Unit
Integra3on
System
VisibillityBlackbox
Whitebox
Inten3on
Acceptance
Func3onal
NonFunc3onal
…
TechniqueSta3c
Dynamic
Execu3onAutoma3c
Manual
![Page 14: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/14.jpg)
![Page 15: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/15.jpg)
Small
Medium
Large
![Page 16: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/16.jpg)
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+
![Page 17: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/17.jpg)
TESTS BY SCOPE
![Page 18: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/18.jpg)
SCOPE
Database
PORT1 PORT2
ADAPTER1
![Page 19: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/19.jpg)
UNIT TEST
![Page 20: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/20.jpg)
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.
![Page 21: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/21.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 22: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/22.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 23: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/23.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 24: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/24.jpg)
TEST DOUBLES
![Page 25: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/25.jpg)
TEST DOUBLES (FAKE)
Fake implementation in order to make test pass.
public UserDaoFake implements UserDao {
public User create(User user) { return ...; } }
![Page 26: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/26.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 27: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/27.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 28: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/28.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 29: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/29.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 30: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/30.jpg)
INTEGRATION TEST WHICH WANT TO BE UNIT TESTS
![Page 31: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/31.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 32: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/32.jpg)
INTEGRATION TEST WHICH WORKS WITH EXTERNAL SYSTEM
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 33: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/33.jpg)
INTEGRATION TEST WHICH WORKS WITH EXTERNAL SYSTEM
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 34: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/34.jpg)
INTEGRATION TEST WHICH USES THE UI
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 35: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/35.jpg)
INTEGRATION TEST WHICH USES THE UI
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 36: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/36.jpg)
SYSTEM TEST
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 37: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/37.jpg)
SYSTEM TEST
Database
Fast Isolates
Repeatable Self-Validating
Timely Inmutable*
Trusted*
![Page 38: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/38.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 39: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/39.jpg)
STRATEGIES
![Page 40: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/40.jpg)
STATIC EVALUATION
➤Informal review ➤Formal review (inspection) ➤Checklists ➤Successive abstraction
➤Walkthrough
![Page 41: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/41.jpg)
DYNAMIC EVALUATION
➤White box ➤Path Coverage ➤Statement Coverage ➤Condition Coverage ➤Function Coverage
➤Black box ➤Equivalence partitioning ➤Boundary values analysis
![Page 42: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/42.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 43: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/43.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 44: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/44.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=predicatenodes+1=numberofregions=4
![Page 45: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/45.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 46: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/46.jpg)
BLACK BOX (PARTITIONING)
Register
Username*
Password(6-10charsincludingnumbers)
![Page 47: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/47.jpg)
BLACK BOX (PARTITIONING)
Username Password
U1:myNick P1:p4ssw0rd
U2:“empty” P2:p4ss
P3:l4rg3p4ssw0rd
P4:passwordRegister
Username*
Password(6-10charsincludingnumbers)
![Page 48: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/48.jpg)
BLACK BOX (PARTITIONING)
Username Password
U1:myNick P1:p4ssw0rd
U2:“empty” P2:p4ss
P3:l4rg3p4ssw0rd
P4:passwordRegister
Username*
Password(6-10charsincludingnumbers)
TestCasesmyNick,p4ssw0rd√myNick,p4ss X
myNick,l4rg3p4ssw0rdX
myNick,passwordX
“empty”,p4ssw0rdX
myNick,p4sw0rd_*X
![Page 49: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/49.jpg)
AUTOMATIC TESTING
![Page 50: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/50.jpg)
4 PHASES-TESTS
1. Set Up 2. Exercise 3. Verify 4. TearDown
![Page 51: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/51.jpg)
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
![Page 52: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/52.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 53: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/53.jpg)
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 }) })
• UserServicetestsuite:
• Whencreateavalidusershouldnotfail√
• Whencreateaninvalidusershouldfail√
Thereportwilllooklike:
![Page 54: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/54.jpg)
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 }) }) })
![Page 55: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/55.jpg)
BDD (SPECIFICATION)Feature:UserregistrationScenario:UsertriestoregistersendingvaliddatasothesystemwillcreatenewaccountGiventheuserhasintroduced<username>and<password>intotheregistrationformAndhasacceptedtermsandagreementsWhensendtheregistrationfromThentheuserwith<username>shouldbecreatedExample:|username|password||myNick|p4ssw0rd|Scenario:UsertriestoregistersendinginvaliddatasothesystemwillrejectuserGiventheuserhasintroduced<username>and<password>intotheregistrationformAndhasacceptedtermsandagreementsWhensendtheregistrationfromThenthesystemshouldnotify<error>Example:|username|password|error||myNick|p4ss|passwordshouldhaveatleast6characters||myNick|l4rg3p4ssword|passwordshouldhaveatlessthan10characters||myNick|password|passwordshouldcontainsatleastanumber|||p4ssword|usernameismandatory|
![Page 56: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/56.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 57: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/57.jpg)
TESTABLE DESIGN
![Page 58: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/58.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
*SeehAp://misko.hevery.com/aAachments/Guide-WriIngTestableCode.pdf
![Page 59: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/59.jpg)
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
![Page 60: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/60.jpg)
MIXING BUSINESS AND CREATION LOGIC
➤Use of new inside class methods for a non value object
➤Use of getInstance
SOLID
![Page 61: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/61.jpg)
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
![Page 62: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/62.jpg)
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
![Page 63: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/63.jpg)
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
![Page 64: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/64.jpg)
TIPS & TRICKS
![Page 65: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/65.jpg)
QUESTIONS & STUPID QUESTIONS
➤Where I place my tests? ➤Whoteststheclasseswhichtestourclasses?
➤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?
➤WhatistheminimumcoverageshouldIexpectformycode?
➤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?
![Page 66: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/66.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>Integra*onTest, …)
➤System tests:
➤Different project
![Page 67: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/67.jpg)
WHERE I PLACE MY TESTS?
JavaProject(TestClassperClass)MyProject/src/main/java/com.groupId.arIfactId.MyClass.javaresources/test/java/com.groupId.arIfactId.MyClassTest.javacom.groupId.arIfactId.it.suite.MyTestCaseIntegraIonTest.javaresources/
NodeJsProjectMyProject/lib/myClass.jsmain.jstest/ut//suiteit/lib/myClassTest.js
JavaProject(ClassperSetUp)MyProject/src/main/…test/java/com.groupId.arIfactId.myclass.<SetUp1>Test.javacom.groupId.arIfactId.myclass.<SetUp2>Test.java…
![Page 68: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/68.jpg)
WHERE I PLACE MY TESTS?
IOSProjectMyIOSProject/MyIOSProject/...appcode...MyIOSProjectTests/...testcode...
AndroidProjectMyProject/AndroidManifest.xmlres/...(resourcesformainapplicaIon)src/main/
…(sourcecodeformainapplicaIon)…test/…(unittests)…
androidTest/…(androidspecifictests/UI,etc)…
tests/AndroidManifest.xml
res/…(resourcesfortests)
src/...(sourcecodefortests)
![Page 69: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/69.jpg)
WHOTESTSTHECLASSESWHICHTESTOURCLASSES?
➤Exactly, this is why it’s so important our tests follow
KISS
![Page 70: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/70.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 validateUserWithNoPasswordShouldThrowsError { ... }
com.mycompany.artifactId.it.TestSteps ...
VS
com.mycompany.artifactId.it.usermanagement.UserCreationSteps ...
![Page 71: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/71.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 72: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/72.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 puristsaysonlyoneasser<on)? ➤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 73: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/73.jpg)
WHATISTHEMINIMUMCODECOVERAGE?
➤“… 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 74: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/74.jpg)
I’VE NEVER WRITE A TEST, WHERE CAN I START?
I’llbetyouabeerthatyoucalledit*[Util|Helper]…
Database
PORT1 PORT2
ADAPTER1
![Page 75: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/75.jpg)
MY CODE IS NOT TESTABLE AT ALL, WHAT CAN I DO?
➤First of all, go to http://refactoring.com/
➤I suggest: 1. Add integration regression test.
2. Remove new from methods and ad it to constructors (this will prepare your class for dependency injection).
3. Creates a constructor which receive every dependency your class will need.
4. Remove static classes and methods (adding the new non-static as a class dependency).
5. Add as much tests as you want to ;)
➤Important!!!Doitstepbystep
![Page 76: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/76.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 77: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/77.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 78: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/78.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 79: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/79.jpg)
SHOULD I VERIFY EVERY SINGLE INTERACTION WITH MY MOCKS?
It depends
![Page 80: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/80.jpg)
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
![Page 81: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/81.jpg)
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/
➤…
![Page 82: Some testing - Everything you should know about testing to go with @pedro_g_s, @flipper83 & @kinisoftware avoiding the hangover](https://reader036.vdocuments.net/reader036/viewer/2022081520/588535251a28ab26518b5c07/html5/thumbnails/82.jpg)
Q&APlaceyourquestionhere!
@delr3ves