SlideShare a Scribd company logo
1 of 38
Download to read offline
The Art of Unit Testing:
How developer should care about code quality
Dmytro Patserkovskyi
2 CULTURE
What is
SOFTWARE TESTING?
DIVE INTO THE HISTORY
3
Let’s look over the philosophy of software
testing 100 years ago.
DIVE INTO THE HISTORY
Debugging
4
Automated
Testing
Manual Testing
SUnit(1989)
JUnit(2001)
1970’s1950’s
DIVE INTO THE HISTORY5
Kent Beck: 1989: "Simple Smalltalk Testing: With Patterns"
”
Software testing it the complex of
techniques include the process of executing
a program or application with the intent of
finding software bugs.
6
PLACE OF UNIT TESTS
7
Let’s find place of unit tests in the ocean of
Software Testing.
AUTOMATION
MANUAL
PLACE OF UNIT TESTS8
DEBUGGING
SOFTWARE
TESTING
COMPONENT
INTEGRATION
UNIT
PLACE OF UNIT TESTS9
SYSTEM
AUTOMATION
TESTING
UNIT TESTS
10
Unit tests – part of code that are designed
to ensure the smallest divisible pieces of
code (units or components) are working
the way they were intended.
UNIT TESTS
@BeforeClass
public void testBeforeSuite() {
prepareMailService();
}
@Test(groups = "mail")
public void testEmailService() {
MailService service= generateMailService();
Assert.assertNotNull(service);
}
@Test(dependsOnMethods = { "testMailService" }, groups="mail")
public void testSending() {
MailService service= generateMailService();
Assert.assertTrue(service.sendMail(subject, message));
}
11 Test
Configuration
Preparations
Assertions
Grouping
UNIT TESTS
Test - part of code, that check logic of another part of code.
Assertions - mechanism for checking results of lome logic,
defines if our unit test will be success or failed.
Configuration - all attributes and properties of test.
Preparations - part of code, that prepares state and context for our tests.
12
UNIT TESTS
Grouping - associates unit tests into groups and suites. Each group or suite should
have common property or characteristic.
13
GROUP SUITE
Contains Methods
Depends on Groups
Annotations Config
Runs Separately
Contains Groups
Flex Configuring
Configuration in XML
Runs Separately
14 CULTURE
WHY ?
UNIT TESTS
Test Dependencies. If a dependent method is fail, all the subsequent test methods
will be skipped, NOT failed.
@Test(groups = "mail")
public void testEmailService() {
MailService service= generateMailService();
Assert.assertNotNull(service);
}
@Test(dependsOnMethods = { "testMailService" }, groups="mail")
public void testSending() {
MailService service= generateMailService();
Assert.assertTrue(service.sendMail(subject, message));
}
15
UNIT TESTS
Parameterized Tests. Run your single test for different data sets.
@DataProvider
public Object[][] smtpHosts() {
return new Object[][]{ {"smtp.host1"}, {"mail.host2"} };
}
@Test(dataProvider = "smtpHosts", groups="mail")
public void testSending(String host) {
MailService service= generateMailService(host);
Assert.assertTrue(service.sendMail(subject, message));
}
16
UNIT TESTS
Rich @Before and @After configuration.
@BeforeSuite - @AfterSuite
@BeforeTest - @AfterTest
@BeforeGroups - @AfterGroups
@BeforeClass - @AfterClass
@BeforeMethod - @AfterMethod
17
PRINCIPLES OF UNIT TESTS
18
We know how to write units! Don’t we?
PRINCIPLES OF UNIT TESTS
19
Principles of Unit Tests:
▹ Easy and fast to run
▹ Unit
▹ Simple
▹ Independent
▹ Checking all cases
▹ Isolate
PRINCIPLES OF UNIT TESTS20
ARCHITECTURE OF PROJECT21
Let’s imagine component for sending emails, and try to cover it with unit tests.
Services:
▹ MailService - service for sending emails. Based on Javax Mail.
▹ LogsStorage - service for collecting logs about mails sending and flushing it
to persistent storage.
▹ LogsMailService - service for work with emails and logs.
PRINCIPLES OF UNIT TESTS
// Bad
@Test(groups = "mail")
public void testEmailSending() {
MailService service= generateMailService();
Assert.assertNotNull(service);
MailBuilder builder= new MailBuilder();
Mail mail = new MailBuilder().
.newMail()
.addSubject("my mail")
.addRecipient(firstRecipient)
.addRecipient(secondRecipient)
.build();
Assert.assertNotNull(mail);
Assert.assertEquals(EXPECT, mail.getSubject());
...
Assert.assertTrue(service.sendMail(mail));
}
22
// Good
@BeforeTest
public void initialize() {
service= generateMailService();
}
@Test(groups = "mail")
public void testEmailSending() {
Assert.assertTrue(
service.sendMail(prepareMail())
);
}
Unit & Simple - each test covers one piece of code.
PRINCIPLES OF UNIT TESTS
// Bad
@Test(groups = "mail")
public void testEmailLogsSuccessful() {
mailLogsStorage.logGood();
Assert.assertEquals(1, mailLogsStorage.getCountGood());
Assert.assertEquals(1, mailLogsStorage.getCountAll());
}
@Test(groups = "mail")
public void testEmailLogsFailed() {
mailLogsStorage.logBad();
Assert.assertEquals(1, mailLogsStorage.getCountBad());
Assert.assertEquals(2, mailLogsStorage.getCountAll());
}
23
// Good
@Test(groups = "mail")
public void testEmailLogsSuccessful() {
mailLogsStorage.logGood();
Assert.assertEquals(1, mailLogsStorage.getCountGood());
Assert.assertEquals(1, mailLogsStorage.getCountAll());
}
@Test(groups = "mail")
public void testEmailLogsFailed() {
mailLogsStorage.logBad();
Assert.assertEquals(1, mailLogsStorage.getCountBad());
Assert.assertEquals(1, mailLogsStorage.getCountAll());
}
@AfterMethod
public void cleanAfter() {
mailLogsStorage.cleanState();
}
Independent - test should runs with random order and in parallel.
PRINCIPLES OF UNIT TESTS
// Bad
@BeforeTest
public void initialize() {
service= generateMailService();
}
@Test(groups = "mail")
public void testEmailSending() {
Assert.assertTrue(
service.sendMail(prepareGoodMail())
);
}
24
// Good
@BeforeTest
public void initialize() {
service= generateMailService();
}
@Test(groups = "mail")
public void testEmailSendingSuccess() {
Assert.assertTrue(
service.sendMail(prepareGoodMail())
);
}
@Test(groups = "mail")
public void testEmailSendingFailed() {
Assert.assertFalse(
service.sendMail(prepareBadMail())
);
}
Checking all cases - tests for success case is not enough.
PRINCIPLES OF UNIT TESTS
// Bad
@Before
public void before() {
service = new LogMailService();
service.setMailService(new MailService());
}
@Test(groups = "mail")
public void testEmailService() {
Assert.assertTrue(service.sendMail(mail));
}
25
// Good
@Before
public void before() {
service = new LogMailService();
}
@Test(groups = "mail")
public void testEmailService() {
MailService mock = mock(MailService.class)
when(mock.sendMail(mail))
.thenReturn(true);
service.setMailService(mock)
Assert.assertTrue(service.sendMail(mail));
times(1, mock.sendMail(mail));
}
Isolate - encapsulated logic should be covered with separated tests.
ISOLATION PHILOSOPHY
26
Mocking - creating objects that simulate
the behaviour of real objects to isolate
part of code for unit testing.
ISOLATION PHILOSOPHY
27
ISOLATION PHILOSOPHY28
Mocks - simulated objects that mimic the behavior of real objects in controlled
ways.
Partial mocks - object, created as shell for real one, when you need to stub
several methods of an object leaving the remainder free to respond to calls
normally.
ISOLATION PHILOSOPHY29
@Before
public void before() {
service = new LogMailService();
}
@Test
public void testEmailService() {
MailService mock = mock(MailService.class)
when(mock.sendMail(mail))
.thenReturn(true);
service.setMailService(mock)
Assert.assertTrue(service.sendMail(mail));
times(1, mock.sendMail(mail));
}
Mocks
ISOLATION PHILOSOPHY30
@Test
public void testLogsRefresh() {
LogsStorage storageSpy = spy(logsStorage);
doReturn(true).when(storageSpy).flush();
storageSpy.refresh();
Assert.assertEquals(1, storageSpy.getCountAll());
times(1, storageSpy.flush());
}
Partial Mocks
ISOLATION PHILOSOPHY31
Looks good… But
ISOLATION PHILOSOPHY
What if… we have private factory method?
Class MailService {
...
private Session createMailSession() {
...
}
}
32
ISOLATION PHILOSOPHY
Use dark power of
33
OR.. create a new class and move all private methods to this as
public. Use dependency injection and mocking. This can force you to
use an unwanted design. Private methods are not an option.
ISOLATION PHILOSOPHY
What if… we have calls to static method of framework?
Class MailService {
...
public Session sendMail() {
...
// Send message
Transport.send(message);
}
}
34
ISOLATION PHILOSOPHY
Use dark power of
35
OR... wrap all static method calls in a separate class and use
dependency injection to mock this object. This will create an extra
layer of unnecessary classes in your application. However, this can
of course be useful if you want to encapsulate the framework to be
able to replace it.
ISOLATION PHILOSOPHY
PowerMock for legacy code with antipatterns.
Mockito is enough for well constructed architecture.
36
QUESTIONS
37
THANK YOU
FOR YOUR TIME
38

More Related Content

What's hot

Swiss army knife Spring
Swiss army knife SpringSwiss army knife Spring
Swiss army knife Spring
Mario Fusco
 
Executing Sql Commands
Executing Sql CommandsExecuting Sql Commands
Executing Sql Commands
leminhvuong
 
J unit스터디슬라이드
J unit스터디슬라이드J unit스터디슬라이드
J unit스터디슬라이드
ksain
 
Concurrent talk
Concurrent talkConcurrent talk
Concurrent talk
rahulrevo
 

What's hot (20)

Reactive programming with RxAndroid
Reactive programming with RxAndroidReactive programming with RxAndroid
Reactive programming with RxAndroid
 
OSGi Puzzlers
OSGi PuzzlersOSGi Puzzlers
OSGi Puzzlers
 
The Ring programming language version 1.9 book - Part 11 of 210
The Ring programming language version 1.9 book - Part 11 of 210The Ring programming language version 1.9 book - Part 11 of 210
The Ring programming language version 1.9 book - Part 11 of 210
 
Swiss army knife Spring
Swiss army knife SpringSwiss army knife Spring
Swiss army knife Spring
 
Parallel Programming With Dot Net
Parallel Programming With Dot NetParallel Programming With Dot Net
Parallel Programming With Dot Net
 
DCN Practical
DCN PracticalDCN Practical
DCN Practical
 
Building responsive application with Rx - confoo - tamir dresher
Building responsive application with Rx - confoo - tamir dresherBuilding responsive application with Rx - confoo - tamir dresher
Building responsive application with Rx - confoo - tamir dresher
 
Core java pract_sem iii
Core java pract_sem iiiCore java pract_sem iii
Core java pract_sem iii
 
Building responsive applications with Rx - CodeMash2017 - Tamir Dresher
Building responsive applications with Rx  - CodeMash2017 - Tamir DresherBuilding responsive applications with Rx  - CodeMash2017 - Tamir Dresher
Building responsive applications with Rx - CodeMash2017 - Tamir Dresher
 
Spock
SpockSpock
Spock
 
Rx 101 Codemotion Milan 2015 - Tamir Dresher
Rx 101   Codemotion Milan 2015 - Tamir DresherRx 101   Codemotion Milan 2015 - Tamir Dresher
Rx 101 Codemotion Milan 2015 - Tamir Dresher
 
Observer pattern
Observer patternObserver pattern
Observer pattern
 
Introduction to Reactive Extensions (Rx)
Introduction to Reactive Extensions (Rx)Introduction to Reactive Extensions (Rx)
Introduction to Reactive Extensions (Rx)
 
Rxandroid
RxandroidRxandroid
Rxandroid
 
Executing Sql Commands
Executing Sql CommandsExecuting Sql Commands
Executing Sql Commands
 
J unit스터디슬라이드
J unit스터디슬라이드J unit스터디슬라이드
J unit스터디슬라이드
 
Concurrent talk
Concurrent talkConcurrent talk
Concurrent talk
 
Writing and using Hamcrest Matchers
Writing and using Hamcrest MatchersWriting and using Hamcrest Matchers
Writing and using Hamcrest Matchers
 
Ice mini guide
Ice mini guideIce mini guide
Ice mini guide
 
Call Back
Call BackCall Back
Call Back
 

Similar to Art of unit testing: How developer should care about code quality

Automating Interaction Testing with UML Sequence Diagrams: Where TDD and UML ...
Automating Interaction Testing with UML Sequence Diagrams: Where TDD and UML ...Automating Interaction Testing with UML Sequence Diagrams: Where TDD and UML ...
Automating Interaction Testing with UML Sequence Diagrams: Where TDD and UML ...
João Pascoal Faria
 
An introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduceAn introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduce
Ananth PackkilDurai
 

Similar to Art of unit testing: How developer should care about code quality (20)

Unit testing with JUnit
Unit testing with JUnitUnit testing with JUnit
Unit testing with JUnit
 
Unit Testing
Unit TestingUnit Testing
Unit Testing
 
Junit mockito and PowerMock in Java
Junit mockito and  PowerMock in JavaJunit mockito and  PowerMock in Java
Junit mockito and PowerMock in Java
 
Unit Testing - Nakov's Talk @ VarnaConf 2013
Unit Testing - Nakov's Talk @ VarnaConf 2013Unit Testing - Nakov's Talk @ VarnaConf 2013
Unit Testing - Nakov's Talk @ VarnaConf 2013
 
Unit testing by Svetlin Nakov
Unit testing by Svetlin NakovUnit testing by Svetlin Nakov
Unit testing by Svetlin Nakov
 
Automating Interaction Testing with UML Sequence Diagrams: Where TDD and UML ...
Automating Interaction Testing with UML Sequence Diagrams: Where TDD and UML ...Automating Interaction Testing with UML Sequence Diagrams: Where TDD and UML ...
Automating Interaction Testing with UML Sequence Diagrams: Where TDD and UML ...
 
Junit and testNG
Junit and testNGJunit and testNG
Junit and testNG
 
Unit/Integration Testing using Spock
Unit/Integration Testing using SpockUnit/Integration Testing using Spock
Unit/Integration Testing using Spock
 
Using xUnit as a Swiss-Aarmy Testing Toolkit
Using xUnit as a Swiss-Aarmy Testing ToolkitUsing xUnit as a Swiss-Aarmy Testing Toolkit
Using xUnit as a Swiss-Aarmy Testing Toolkit
 
Unit test
Unit testUnit test
Unit test
 
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
 
Android testing
Android testingAndroid testing
Android testing
 
Celery with python
Celery with pythonCelery with python
Celery with python
 
Testing in Scala. Adform Research
Testing in Scala. Adform ResearchTesting in Scala. Adform Research
Testing in Scala. Adform Research
 
Testing in Scala by Adform research
Testing in Scala by Adform researchTesting in Scala by Adform research
Testing in Scala by Adform research
 
Describe's Full of It's
Describe's Full of It'sDescribe's Full of It's
Describe's Full of It's
 
An introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduceAn introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduce
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
Advances in Unit Testing: Theory and Practice
Advances in Unit Testing: Theory and PracticeAdvances in Unit Testing: Theory and Practice
Advances in Unit Testing: Theory and Practice
 
Unit Testing in Java
Unit Testing in JavaUnit Testing in Java
Unit Testing in Java
 

Recently uploaded

Standard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power PlayStandard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power Play
Epec Engineered Technologies
 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
ssuser89054b
 
VIP Call Girls Palanpur 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Palanpur 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Palanpur 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Palanpur 7001035870 Whatsapp Number, 24/07 Booking
dharasingh5698
 
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoor
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoorTop Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoor
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoor
dharasingh5698
 
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
dharasingh5698
 

Recently uploaded (20)

Standard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power PlayStandard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power Play
 
Generative AI or GenAI technology based PPT
Generative AI or GenAI technology based PPTGenerative AI or GenAI technology based PPT
Generative AI or GenAI technology based PPT
 
Call Girls Wakad Call Me 7737669865 Budget Friendly No Advance Booking
Call Girls Wakad Call Me 7737669865 Budget Friendly No Advance BookingCall Girls Wakad Call Me 7737669865 Budget Friendly No Advance Booking
Call Girls Wakad Call Me 7737669865 Budget Friendly No Advance Booking
 
FEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced Loads
FEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced LoadsFEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced Loads
FEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced Loads
 
Bhosari ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready For ...
Bhosari ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready For ...Bhosari ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready For ...
Bhosari ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready For ...
 
Unit 1 - Soil Classification and Compaction.pdf
Unit 1 - Soil Classification and Compaction.pdfUnit 1 - Soil Classification and Compaction.pdf
Unit 1 - Soil Classification and Compaction.pdf
 
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 
VIP Call Girls Palanpur 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Palanpur 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Palanpur 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Palanpur 7001035870 Whatsapp Number, 24/07 Booking
 
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Netaji Nagar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
 
(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7
(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7
(INDIRA) Call Girl Meerut Call Now 8617697112 Meerut Escorts 24x7
 
Thermal Engineering-R & A / C - unit - V
Thermal Engineering-R & A / C - unit - VThermal Engineering-R & A / C - unit - V
Thermal Engineering-R & A / C - unit - V
 
(INDIRA) Call Girl Bhosari Call Now 8617697112 Bhosari Escorts 24x7
(INDIRA) Call Girl Bhosari Call Now 8617697112 Bhosari Escorts 24x7(INDIRA) Call Girl Bhosari Call Now 8617697112 Bhosari Escorts 24x7
(INDIRA) Call Girl Bhosari Call Now 8617697112 Bhosari Escorts 24x7
 
Double Revolving field theory-how the rotor develops torque
Double Revolving field theory-how the rotor develops torqueDouble Revolving field theory-how the rotor develops torque
Double Revolving field theory-how the rotor develops torque
 
data_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdfdata_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdf
 
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoor
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoorTop Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoor
Top Rated Call Girls In chittoor 📱 {7001035870} VIP Escorts chittoor
 
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Ankleshwar 7001035870 Whatsapp Number, 24/07 Booking
 
Hostel management system project report..pdf
Hostel management system project report..pdfHostel management system project report..pdf
Hostel management system project report..pdf
 
Unleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leapUnleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leap
 
Introduction to Serverless with AWS Lambda
Introduction to Serverless with AWS LambdaIntroduction to Serverless with AWS Lambda
Introduction to Serverless with AWS Lambda
 

Art of unit testing: How developer should care about code quality

  • 1. The Art of Unit Testing: How developer should care about code quality Dmytro Patserkovskyi
  • 3. DIVE INTO THE HISTORY 3 Let’s look over the philosophy of software testing 100 years ago.
  • 4. DIVE INTO THE HISTORY Debugging 4 Automated Testing Manual Testing SUnit(1989) JUnit(2001) 1970’s1950’s
  • 5. DIVE INTO THE HISTORY5 Kent Beck: 1989: "Simple Smalltalk Testing: With Patterns"
  • 6. ” Software testing it the complex of techniques include the process of executing a program or application with the intent of finding software bugs. 6
  • 7. PLACE OF UNIT TESTS 7 Let’s find place of unit tests in the ocean of Software Testing.
  • 8. AUTOMATION MANUAL PLACE OF UNIT TESTS8 DEBUGGING SOFTWARE TESTING
  • 9. COMPONENT INTEGRATION UNIT PLACE OF UNIT TESTS9 SYSTEM AUTOMATION TESTING
  • 10. UNIT TESTS 10 Unit tests – part of code that are designed to ensure the smallest divisible pieces of code (units or components) are working the way they were intended.
  • 11. UNIT TESTS @BeforeClass public void testBeforeSuite() { prepareMailService(); } @Test(groups = "mail") public void testEmailService() { MailService service= generateMailService(); Assert.assertNotNull(service); } @Test(dependsOnMethods = { "testMailService" }, groups="mail") public void testSending() { MailService service= generateMailService(); Assert.assertTrue(service.sendMail(subject, message)); } 11 Test Configuration Preparations Assertions Grouping
  • 12. UNIT TESTS Test - part of code, that check logic of another part of code. Assertions - mechanism for checking results of lome logic, defines if our unit test will be success or failed. Configuration - all attributes and properties of test. Preparations - part of code, that prepares state and context for our tests. 12
  • 13. UNIT TESTS Grouping - associates unit tests into groups and suites. Each group or suite should have common property or characteristic. 13 GROUP SUITE Contains Methods Depends on Groups Annotations Config Runs Separately Contains Groups Flex Configuring Configuration in XML Runs Separately
  • 15. UNIT TESTS Test Dependencies. If a dependent method is fail, all the subsequent test methods will be skipped, NOT failed. @Test(groups = "mail") public void testEmailService() { MailService service= generateMailService(); Assert.assertNotNull(service); } @Test(dependsOnMethods = { "testMailService" }, groups="mail") public void testSending() { MailService service= generateMailService(); Assert.assertTrue(service.sendMail(subject, message)); } 15
  • 16. UNIT TESTS Parameterized Tests. Run your single test for different data sets. @DataProvider public Object[][] smtpHosts() { return new Object[][]{ {"smtp.host1"}, {"mail.host2"} }; } @Test(dataProvider = "smtpHosts", groups="mail") public void testSending(String host) { MailService service= generateMailService(host); Assert.assertTrue(service.sendMail(subject, message)); } 16
  • 17. UNIT TESTS Rich @Before and @After configuration. @BeforeSuite - @AfterSuite @BeforeTest - @AfterTest @BeforeGroups - @AfterGroups @BeforeClass - @AfterClass @BeforeMethod - @AfterMethod 17
  • 18. PRINCIPLES OF UNIT TESTS 18 We know how to write units! Don’t we?
  • 19. PRINCIPLES OF UNIT TESTS 19 Principles of Unit Tests: ▹ Easy and fast to run ▹ Unit ▹ Simple ▹ Independent ▹ Checking all cases ▹ Isolate
  • 21. ARCHITECTURE OF PROJECT21 Let’s imagine component for sending emails, and try to cover it with unit tests. Services: ▹ MailService - service for sending emails. Based on Javax Mail. ▹ LogsStorage - service for collecting logs about mails sending and flushing it to persistent storage. ▹ LogsMailService - service for work with emails and logs.
  • 22. PRINCIPLES OF UNIT TESTS // Bad @Test(groups = "mail") public void testEmailSending() { MailService service= generateMailService(); Assert.assertNotNull(service); MailBuilder builder= new MailBuilder(); Mail mail = new MailBuilder(). .newMail() .addSubject("my mail") .addRecipient(firstRecipient) .addRecipient(secondRecipient) .build(); Assert.assertNotNull(mail); Assert.assertEquals(EXPECT, mail.getSubject()); ... Assert.assertTrue(service.sendMail(mail)); } 22 // Good @BeforeTest public void initialize() { service= generateMailService(); } @Test(groups = "mail") public void testEmailSending() { Assert.assertTrue( service.sendMail(prepareMail()) ); } Unit & Simple - each test covers one piece of code.
  • 23. PRINCIPLES OF UNIT TESTS // Bad @Test(groups = "mail") public void testEmailLogsSuccessful() { mailLogsStorage.logGood(); Assert.assertEquals(1, mailLogsStorage.getCountGood()); Assert.assertEquals(1, mailLogsStorage.getCountAll()); } @Test(groups = "mail") public void testEmailLogsFailed() { mailLogsStorage.logBad(); Assert.assertEquals(1, mailLogsStorage.getCountBad()); Assert.assertEquals(2, mailLogsStorage.getCountAll()); } 23 // Good @Test(groups = "mail") public void testEmailLogsSuccessful() { mailLogsStorage.logGood(); Assert.assertEquals(1, mailLogsStorage.getCountGood()); Assert.assertEquals(1, mailLogsStorage.getCountAll()); } @Test(groups = "mail") public void testEmailLogsFailed() { mailLogsStorage.logBad(); Assert.assertEquals(1, mailLogsStorage.getCountBad()); Assert.assertEquals(1, mailLogsStorage.getCountAll()); } @AfterMethod public void cleanAfter() { mailLogsStorage.cleanState(); } Independent - test should runs with random order and in parallel.
  • 24. PRINCIPLES OF UNIT TESTS // Bad @BeforeTest public void initialize() { service= generateMailService(); } @Test(groups = "mail") public void testEmailSending() { Assert.assertTrue( service.sendMail(prepareGoodMail()) ); } 24 // Good @BeforeTest public void initialize() { service= generateMailService(); } @Test(groups = "mail") public void testEmailSendingSuccess() { Assert.assertTrue( service.sendMail(prepareGoodMail()) ); } @Test(groups = "mail") public void testEmailSendingFailed() { Assert.assertFalse( service.sendMail(prepareBadMail()) ); } Checking all cases - tests for success case is not enough.
  • 25. PRINCIPLES OF UNIT TESTS // Bad @Before public void before() { service = new LogMailService(); service.setMailService(new MailService()); } @Test(groups = "mail") public void testEmailService() { Assert.assertTrue(service.sendMail(mail)); } 25 // Good @Before public void before() { service = new LogMailService(); } @Test(groups = "mail") public void testEmailService() { MailService mock = mock(MailService.class) when(mock.sendMail(mail)) .thenReturn(true); service.setMailService(mock) Assert.assertTrue(service.sendMail(mail)); times(1, mock.sendMail(mail)); } Isolate - encapsulated logic should be covered with separated tests.
  • 26. ISOLATION PHILOSOPHY 26 Mocking - creating objects that simulate the behaviour of real objects to isolate part of code for unit testing.
  • 28. ISOLATION PHILOSOPHY28 Mocks - simulated objects that mimic the behavior of real objects in controlled ways. Partial mocks - object, created as shell for real one, when you need to stub several methods of an object leaving the remainder free to respond to calls normally.
  • 29. ISOLATION PHILOSOPHY29 @Before public void before() { service = new LogMailService(); } @Test public void testEmailService() { MailService mock = mock(MailService.class) when(mock.sendMail(mail)) .thenReturn(true); service.setMailService(mock) Assert.assertTrue(service.sendMail(mail)); times(1, mock.sendMail(mail)); } Mocks
  • 30. ISOLATION PHILOSOPHY30 @Test public void testLogsRefresh() { LogsStorage storageSpy = spy(logsStorage); doReturn(true).when(storageSpy).flush(); storageSpy.refresh(); Assert.assertEquals(1, storageSpy.getCountAll()); times(1, storageSpy.flush()); } Partial Mocks
  • 32. ISOLATION PHILOSOPHY What if… we have private factory method? Class MailService { ... private Session createMailSession() { ... } } 32
  • 33. ISOLATION PHILOSOPHY Use dark power of 33 OR.. create a new class and move all private methods to this as public. Use dependency injection and mocking. This can force you to use an unwanted design. Private methods are not an option.
  • 34. ISOLATION PHILOSOPHY What if… we have calls to static method of framework? Class MailService { ... public Session sendMail() { ... // Send message Transport.send(message); } } 34
  • 35. ISOLATION PHILOSOPHY Use dark power of 35 OR... wrap all static method calls in a separate class and use dependency injection to mock this object. This will create an extra layer of unnecessary classes in your application. However, this can of course be useful if you want to encapsulate the framework to be able to replace it.
  • 36. ISOLATION PHILOSOPHY PowerMock for legacy code with antipatterns. Mockito is enough for well constructed architecture. 36