SlideShare a Scribd company logo
The Test Way
Why to test? Unit Test, JUnit, TDD, mutation tests
and more
https://medium.com/@grinfeld_433https://github.com/grinfeldGrinfeld Mikhail
https://github.com/grinfeld/beerpub
Agenda
1. History
2. Test Philosophy
a. No tests
b. QA only
c. Test pyramid
d. Unit, component, integration tests
i. Junit
1. Unit tests
2. Component Tests
ii. clean code (name conventions and etc)
iii. private vs. public
iv. TDD (BDD)
v. live coding TDD
e. Who tests the tester (hint: Mutation tests)
f. Integration Tests
3. The whole pipeline
History of Tests
● Until 1956 - debugging oriented period, where testing was often associated with debugging: there was no clear
difference between testing and debugging.
● 1957-1978 - demonstration oriented period where debugging and testing were distinguished. During that period
the main reason for testing was to prove that software satisfied the requirements (positive tests).
● 1979-1982 - destruction oriented period, where the goal was to find errors (negative tests).
● 1983-1987 - evaluation oriented period: intention was to evaluate the product and measure its quality during the
software lifecycle.
● Since 1988 - prevention oriented period, tests were used to detect and prevent faults, and to demonstrate that
software satisfied its specification.
https://en.wikiversity.org/wiki/Software_testing/History_of_testing
Test Philosophy
1. (only) our customers/users should test
2. only QA should test
3. Write code first, then test it
4. Test Driven Development (TDD) - before creating source code, unit tests are created and after this - or in an iterative process - the
system is created. Red, Green, Yellow development.
Kent Beck (creator of XP - Extreme Programming and one of creators of Agile Manifesto) - https://twitter.com/KentBeck
5. Behaviour Driven Development (BDD)
BDD is under technical viewpoint the same like TDD. But BDD devotes to following aspect: because TDD uses test centered vocabulary (e.g. test
cases, test suite, test ...) this can lead to thinking mostly of testing - but TDD is however a design process. BDD tries to improve this by a common
vocabulary, because language influences the way of thinking
https://en.wikiversity.org/wiki/Software_testing/History_of_testing
No Tests
Advantages
1. Time of development (developers are not writing tests) *
2. Cost of development (less time to develop features) *
“I get paid for code that works, not for tests, so my philosophy is to test as little as possible...” Kent Beck (Stackoverflow)
Disadvantages
1. Bugs… (at least, as long as developers are not “ninjas” that never create bugs)
2. Old bugs (nobody remembers/knows what a certain code does, why and so on)
3. Looking for the root cause is painful and time consuming
4. Many smaller bugs are hidden behind bigger bugs.
5. Interruptions in the current development process
6. Fear of changing code, since it could (and will) harm customers. Especially big changes/refactoring.
Tests
1. Eliminate fear for changing code
(increase developer confidence to
change,fix and improve code)
2. Deliver better product to end point
customers
3. Create de-facto “design by contract” for
units, components, services and
products
4. Decrease fix-bug life cycle by
discovering bugs on early stages
“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 (Stackoverflow)
Tests
Positive tests:
implementing scenarios with valid input and verifying that received result is valid
Negative tests:
implementing scenarios with invalid input and verifying exceptions, errors and so
on
QA Only (End-to-End Tests)
Advantages
1. Time of development (developers are not writing tests) *
2. Cost of development (less time to develop feature) *
3. Bugs don’t reach end point customer
4. Tests product as black box :)
“I get paid for code that works, not for tests, so my philosophy is to test as little as possible...” Kent Beck (Stackoverflow)
Disadvantages
1. The team completed their coding milestone a week/month/etc later (and worked a lot of overtime).
2. Looking for the root cause for a failing end-to-end test is painful and can take a long time.
3. Partner failures and lab failures ruin the test results continuously.
4. Many smaller bugs are hidden behind bigger bugs.
5. Tests are flaky at times.
6. Developers have to wait until the following day to know if a fix worked or not.
7. Interruptions in the current development process
8. Tests product as black box :(
9. Still Fear of changing code
https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html
Unit Tests
Unit tests are short code fragments created by
programmers to tests small units (methods,
functions…).
Ideally, each test case is independent from the
others. Substitutes such as method stubs, mock
objects, fakes, and test harnesses can be used
to assist testing a module in isolation. Unit tests
are typically written and run by software
developers to ensure that code meets its design
and behaves as intended.
https://martinfowler.com/bliki/UnitTest.html
https://en.wikipedia.org/wiki/Unit_testing
Unit Tests
● Test each part of the program and show that the individual parts are correct.
● Test Execution is (should be) fast (Fast - when tests run slow, you won’t want to run them frequently - Uncle
Bob)
● Can be executed at any time (Independent - you should be able to run each test independently and run the
tests in any order and Repeatable - you should be able to run them in any environment - Uncle Bob)
● Kind of White Box Testing
● Unit Testing tests only the functionality of the units themselves and may not catch integration errors, or other
system-wide issues
● Focus on behavior of a single module
● unit tests do not verify whether your code works with external dependencies correctly.
● usually executed by developer
● Looking for errors is easy
● Maintenance of unit test is (should be) cheap
https://www.guru99.com/unit-test-vs-integration-test.html
More about unit tests see at chapter 9 in Clean Code by Uncle Bob
JUnit
import java.util.*;
public class Utils {
public static <V> V deNull(V value, V defValue) {
return Optional.ofNullable(value).orElse(defValue);
}
}
Junit 5
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
If we are using an IDE that is bundled with an older JUnit 5 version, it
throws an exception when we try to run our unit tests by using our IDE. We
can fix this problem by adding the following dependencies to our POM file:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- if you want to run old junit4 tests, should -->
<!-- add junit-vintage-engine dependency -->
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
JUnit unit tests
import org.junit.jupiter.api.*;
import java.util.*;
import static org.assertj.core.api.Assertions.assertThat
@ExtendWith(SpringExtension.class)
class UtilsTest {
@Nested
@DisplayName("method: deNull")
class DeNullTest {
@Test
@DisplayName("when method receives null and default is string, should return default value as string")
void whenNullAndDefaultString_expectedDefStringValue() {
assertThat(CollectionUtils.deNull(null, "else"))
.isNotNull().isInstanceOf(String.class).isEqualTo("else");
}
@Test
@DisplayName("when method receives null and default is Integer, should return default Integer value")
void whenNullAndDefaultInteger_expectedDefInetegerValue() {
assertThat(CollectionUtils.deNull(null, new Integer(1))).isNotNull().isInstanceOf(Integer.class).isEqualTo(1);
}
@Test
@DisplayName("when method receives null and default is primitive int, should return default Integer (wrapper) value")
void whenNullAndDefaultPrimitiveInt_expectedDefInetegerValue() {
assertThat(CollectionUtils.deNull(null, 1)).isNotNull().isInstanceOf(Integer.class).isEqualTo(1);
}
}
}
Component Tests
Component - a logical unit which combines a number of classes according to
some business logic
Component testing is a method where testing of each component in an application
is done separately. Component testing is also known as module, unit or program
testing. It finds the defects in the module and verifies the functioning of software.
Component tests can be large or small, according to how you define your
components. The essence of the difference is that component tests deliberately
neglect parts of the system outside the scope of the test. This is usually done by
manipulating the system through internal code interfaces, using mocks and so on.
https://sqa.stackexchange.com/questions/12630/what-is-component-testing-and-how-to-write-component-test-cases
https://martinfowler.com/bliki/ComponentTest.html
Component Tests
In Spring-Boot (ver. 2.x, aka spring 5), Mockito (2.x) we have following tools for component tests:
@SpyBean - Annotation that can be used to apply Mockito spies to a Spring ApplicationContext. Can be used as a
class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner
@MockBean - Annotation that can be used to add mocks to a Spring ApplicationContext. Can be used as a class level
annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner
@Captor (ArgumentCaptor) - Use it to capture argument values for further assertions in Mockito
ArgumentMatcher - Allows creating customized argument matchers
https://static.javadoc.io/org.mockito/mockito-core/2.19.1/index.html?org/mockito/Mockito.html
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-mocking-beans
http://www.baeldung.com/mockito-annotations
Component Tests
https://github.com/grinfeld/beerpub/blob/master/src/main/java/com/mikerusoft/mikhail/component/simple/UserController.java https://github.com/grinfeld/beerpub/blob/master/src/test/java/com/mikerusoft/mikhail/component/simple/UserControllerTest.javahttps://github.com/grinfeld/beerpub/blob/master/src/test/java/com/mikerusoft/mikhail/component/simple/UserControllerMvcTest.java
Clean Code
1. Treat your tests same as your code (well written, no duplications and so on) -
https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882
2. Name/Structure convention:
a. Names for your test methods should describe what a test does and what the expected result
is. It helps to understand easier what is wrong when failure occurs. Example:
withSomePrerequisite_whenSomeCondition_expectedSomeResult
b. Test body should be short and easy to read (understand). If you have long preparation stage,
move it into different method (e.g. setupTest() ). The second line is the action itself we want to
test, and the last one - assertion (again, too many lines - move it to dedicated method). Rule of
thumb for test body: 2-8 lines maximum.
3. Boy Scouts have a rule: “Always leave the campground cleaner than you
found it”. Robert C. Martin (aka, Uncle Bob) re-phrased this rule so: “Always
leave the code you’re editing a little bit better than before you found it”
(https://cleancoders.com/). It’s relevant for tests, same as for your feature
code.
Nice Quotes from Dave Westerveld (https://twitter.com/offbeattesting/status/1019912503520735232?s=19)
"The unit tests suck - we need to do integration testing."
"These UI tests suck - we need to do unit testing"
"BDD/TDD/*DD sucks - we need a different method"
Conclusion:
Writing bad tests is a problem that doesn't go away when you change where/how you write the
tests
Clean Code
Public vs. Private (or Maintable tests)
Now we live in the era when almost all people (developers) agree that it’s essentially
important to write tests for our code. WOW—it’s (almost) a consensus.
But now we have another question: how do we maintain tests and not tests maintain us?
Let’s write tests for private methods (similar logic like components tests, and then mocking
private tests with limit options, e.g. boolean private method mocked with only 3 options:
true, false, exception. It’s possible with Powermock)
As a result, it becomes difficult to make changes, because of a need to rewrite a lot of tests.
Since we change implementation, we will spend a lot of time by rewriting tests, instead of
add(new)/delete(unused)/etc tests.
Conclusion: we want to interfere, as minimum as possible, in implementation details.
Junit - Summary
1. Fast. Having a unit test suite that takes ages to run debases most of the advantages. The longer it takes to run, the
more developers put off running tests until commit time, or start skipping them all together.
2. Isolated. It can be tempting to have a bunch of common set-up tasks used by multiple unit tests, but where possible,
try to limit this. It ties unit tests together in ways that can be harder to isolate them in future.
3. Succinct. If your unit tests are hard to set up and complicated to write, it’s a good sign that the code you are trying to
test is either too complex, or badly structured. Either way, it’s a good sign that a refactor might be required.
4. Easy to Understand. Good naming of unit tests is vital. You should be able to read a test name and understand
what the test is testing, what results the test is expecting, and why it’s failing. Do not be afraid to make unit test
names long – the more information the better. After all, you should only see them when they are failing.
5. Reliable. Tests shouldn’t be bound to a given environment or rely on external factors to work. They should work
100% of the time, or they are not going to fulfil their purpose.
TDD
Test-driven development (TDD) is a software development process that relies on the
repetition of a very short development cycle: requirements are turned into very specific test
cases, then the software is improved to pass the new tests only. This is opposed to software
development that allows software to be added that is not proven to meet requirements.
TDD is guiding us to develop code in more usable way (since the code is used by tests and
we start from tests)
Red-Green-Yellow approach
Red - The development of every new feature should start with a failing test.
Green - Enough production code should be written to make the test pass.
Refactor - Improve the structure of the code to ease future changes and maintenance.
http://www.giorgiosironi.com/2010/03/tdd-checklist-red-green-refactor-in.html
https://en.wikipedia.org/wiki/Test-driven_development
TDD
Requirements
Beer pub (credits to one of Wix meetups on a different subject where they introduced Beer Factory example):
1. Order Beer by type and can size
2. Check if in stock
a. If yes - return Beer with price
b. If no - return error
Let’s try it :)
Who tests the tester?
Great, we wrote the tests, but who said they are good enough?
We can run tests with coverage. It helps to check that we “have touched” all (or a lot of) lines in code.
But…
Do our tests check code or they are simply assertTrue(true).
Do we need somebody to look into our tests? Definitely, yes - during the code review. Is it enough? No!
At this stage, mutation tests could help us.
Mutation Testing is a type of software testing where we mutate (change) certain statements in the source
code and check if the test cases are able to find the errors (https://www.guru99.com/mutation-testing.html)
Package for mutation tests in Java: http://pitest.org/
Integration Tests
1. The idea behind Integration Testing is to combine modules in the application
and test as a group to see that they are working fine
2. It is kind of Black Box Testing
3. It usually carried out after Unit Testing and before System Testing
4. Integrating testing may detect errors when modules are integrated to build the
overall system
5. It pays attention to integration among modules
6. Integration tests verify that your code works with external dependencies
correctly.
7. It is usually executed by QA team (update: more and more companies work
with “NO QA” philosophy, so Integration Tests become the part of developer
job)
https://www.guru99.com/unit-test-vs-integration-test.html
Confidence
1. Unit and Component Tests by developers (with coverage)
2. Mutation Tests
3. Code Review
4. CI (Continuous integration): running tests on every commit or merge to develop/master branch
5. Integration Tests by QA team
6. CD (Continuous delivery) - running tests nightly
7. Automation during all stages
8. Stress and Load Tests (dedicated QA team)
9. Chaos Monkey on QA, Staging, Production environments (https://github.com/Netflix/SimianArmy/wiki/Chaos-Monkey) and for
spring-boot: https://codecentric.github.io/chaos-monkey-spring-boot/
Fast delivery and new
high-quality features
Confidence to make
changes and introduce
new technologies
Reducing ping-pong
between Developers
and QA teams (and
Support team)
When you develop your code - make it testable (for e.g. TDD makes it easier, since you start from writing
tests)
Thank You
https://github.com/grinfeld/beerpub
https://en.wikiversity.org/wiki/Software_testing/History_of_testing
https://en.wikipedia.org/wiki/Extreme_programming#Origins
http://agilemanifesto.org
https://twitter.com/KentBeck
https://stackoverflow.com/questions/153234/how-deep-are-your-unit-tests?answertab=oldest#tab-top
https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html
https://martinfowler.com/bliki/UnitTest.html
https://en.wikipedia.org/wiki/Unit_testing
https://www.guru99.com/unit-test-vs-integration-test.html
https://sqa.stackexchange.com/questions/12630/what-is-component-testing-and-how-to-write-component-test-cases
https://martinfowler.com/bliki/ComponentTest.html
http://www.baeldung.com/mockito-annotations
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-mocking-beans
https://static.javadoc.io/org.mockito/mockito-core/2.19.1/index.html?org/mockito/Mockito.html
Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882
https://twitter.com/unclebobmartin
https://cleancoders.com/
https://en.wikipedia.org/wiki/Test-driven_development
http://www.giorgiosironi.com/2010/03/tdd-checklist-red-green-refactor-in.html
https://github.com/Netflix/SimianArmy/wiki/Chaos-Monkey)
https://dzone.com/articles/spring-di-patterns-the-good-the-bad-and-the-ugly
https://github.com/powermock/powermock
https://www.guru99.com/mutation-testing.html
http://pitest.org/
https://twitter.com/offbeattesting/status/1019912503520735232?s=19
https://manifesto.co.uk/unit-testing-best-practices-java/
https://codecentric.github.io/chaos-monkey-spring-boot/

More Related Content

PPT
Google test training
KEY
Unit Testing Your Application
PDF
Android TDD
PPTX
Unit Testing Android Applications
PDF
Unit testing (eng)
ODP
Testing In Java
PDF
When develpment met test(shift left testing)
PPTX
Cpp Testing Techniques Tips and Tricks - Cpp Europe
Google test training
Unit Testing Your Application
Android TDD
Unit Testing Android Applications
Unit testing (eng)
Testing In Java
When develpment met test(shift left testing)
Cpp Testing Techniques Tips and Tricks - Cpp Europe

What's hot (20)

PDF
Is this how you hate unit testing?
PDF
Unit Test + Functional Programming = Love
PDF
A Software Tester's Travels from the Land of the Waterfall to the Land of Agi...
PDF
Php unit (eng)
PDF
Refactoring Legacy Code
PDF
How and what to unit test
PPT
Unit testing
PDF
Clean Unit Test Patterns
PPTX
Testing for Android: When, Where, and How to Successfully Use Test Automation
PPTX
Creating a reasonable project boilerplate
PDF
Oh so you test? - A guide to testing on Android from Unit to Mutation
PDF
Unit Testing
PPTX
Android tdd
PDF
Test driven development_continuous_integration
PPT
Testing ppt
ODP
Android Test Driven Development
PPT
Testing and Mocking Object - The Art of Mocking.
PDF
ES3-2020-P2 Bowling Game Kata
PPT
Unit Testing
PPTX
JUnit 5: What's New and What's Coming - Spring I/O 2019
Is this how you hate unit testing?
Unit Test + Functional Programming = Love
A Software Tester's Travels from the Land of the Waterfall to the Land of Agi...
Php unit (eng)
Refactoring Legacy Code
How and what to unit test
Unit testing
Clean Unit Test Patterns
Testing for Android: When, Where, and How to Successfully Use Test Automation
Creating a reasonable project boilerplate
Oh so you test? - A guide to testing on Android from Unit to Mutation
Unit Testing
Android tdd
Test driven development_continuous_integration
Testing ppt
Android Test Driven Development
Testing and Mocking Object - The Art of Mocking.
ES3-2020-P2 Bowling Game Kata
Unit Testing
JUnit 5: What's New and What's Coming - Spring I/O 2019
Ad

Similar to The Test way (20)

PPTX
presentation des google test dans un contexte de tdd
DOCX
Test driven development and unit testing with examples in C++
PDF
TDD Workshop UTN 2012
PPTX
Getting Started with Test-Driven Development at Longhorn PHP 2023
PPTX
Fundamentals of DevOps and CI/CD
PPTX
Test-Driven-Development.pptx
PPTX
Test-Driven Development In Action
PPTX
Intro to Continuous Integration
PPTX
Software Testing, Everyone's responsibility
PDF
TDD and Related Techniques for Non Developers (2012)
PDF
Hadoop testing workshop - july 2013
PPT
ISTQB / ISEB Foundation Exam Practice - 2
PPTX
Unit Testing
PPTX
Tdd is not about testing (C++ version)
PPT
ISTQB, ISEB Lecture Notes- 2
PPTX
Test Driven Development
PDF
Testing - How Vital and How Easy to use
PPTX
Tdd is not about testing (OOP)
PDF
Software Testing
PDF
201008 Software Testing Notes (part 1/2)
presentation des google test dans un contexte de tdd
Test driven development and unit testing with examples in C++
TDD Workshop UTN 2012
Getting Started with Test-Driven Development at Longhorn PHP 2023
Fundamentals of DevOps and CI/CD
Test-Driven-Development.pptx
Test-Driven Development In Action
Intro to Continuous Integration
Software Testing, Everyone's responsibility
TDD and Related Techniques for Non Developers (2012)
Hadoop testing workshop - july 2013
ISTQB / ISEB Foundation Exam Practice - 2
Unit Testing
Tdd is not about testing (C++ version)
ISTQB, ISEB Lecture Notes- 2
Test Driven Development
Testing - How Vital and How Easy to use
Tdd is not about testing (OOP)
Software Testing
201008 Software Testing Notes (part 1/2)
Ad

Recently uploaded (20)

PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Empathic Computing: Creating Shared Understanding
PDF
Machine learning based COVID-19 study performance prediction
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
A comparative analysis of optical character recognition models for extracting...
PDF
Encapsulation theory and applications.pdf
PPTX
Tartificialntelligence_presentation.pptx
PDF
Heart disease approach using modified random forest and particle swarm optimi...
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PPTX
cloud_computing_Infrastucture_as_cloud_p
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
1. Introduction to Computer Programming.pptx
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PDF
A comparative study of natural language inference in Swahili using monolingua...
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Agricultural_Statistics_at_a_Glance_2022_0.pdf
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Empathic Computing: Creating Shared Understanding
Machine learning based COVID-19 study performance prediction
Programs and apps: productivity, graphics, security and other tools
A comparative analysis of optical character recognition models for extracting...
Encapsulation theory and applications.pdf
Tartificialntelligence_presentation.pptx
Heart disease approach using modified random forest and particle swarm optimi...
NewMind AI Weekly Chronicles - August'25-Week II
cloud_computing_Infrastucture_as_cloud_p
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
MIND Revenue Release Quarter 2 2025 Press Release
Digital-Transformation-Roadmap-for-Companies.pptx
1. Introduction to Computer Programming.pptx
Building Integrated photovoltaic BIPV_UPV.pdf
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Accuracy of neural networks in brain wave diagnosis of schizophrenia
A comparative study of natural language inference in Swahili using monolingua...

The Test way

  • 1. The Test Way Why to test? Unit Test, JUnit, TDD, mutation tests and more https://medium.com/@grinfeld_433https://github.com/grinfeldGrinfeld Mikhail https://github.com/grinfeld/beerpub
  • 2. Agenda 1. History 2. Test Philosophy a. No tests b. QA only c. Test pyramid d. Unit, component, integration tests i. Junit 1. Unit tests 2. Component Tests ii. clean code (name conventions and etc) iii. private vs. public iv. TDD (BDD) v. live coding TDD e. Who tests the tester (hint: Mutation tests) f. Integration Tests 3. The whole pipeline
  • 3. History of Tests ● Until 1956 - debugging oriented period, where testing was often associated with debugging: there was no clear difference between testing and debugging. ● 1957-1978 - demonstration oriented period where debugging and testing were distinguished. During that period the main reason for testing was to prove that software satisfied the requirements (positive tests). ● 1979-1982 - destruction oriented period, where the goal was to find errors (negative tests). ● 1983-1987 - evaluation oriented period: intention was to evaluate the product and measure its quality during the software lifecycle. ● Since 1988 - prevention oriented period, tests were used to detect and prevent faults, and to demonstrate that software satisfied its specification. https://en.wikiversity.org/wiki/Software_testing/History_of_testing
  • 4. Test Philosophy 1. (only) our customers/users should test 2. only QA should test 3. Write code first, then test it 4. Test Driven Development (TDD) - before creating source code, unit tests are created and after this - or in an iterative process - the system is created. Red, Green, Yellow development. Kent Beck (creator of XP - Extreme Programming and one of creators of Agile Manifesto) - https://twitter.com/KentBeck 5. Behaviour Driven Development (BDD) BDD is under technical viewpoint the same like TDD. But BDD devotes to following aspect: because TDD uses test centered vocabulary (e.g. test cases, test suite, test ...) this can lead to thinking mostly of testing - but TDD is however a design process. BDD tries to improve this by a common vocabulary, because language influences the way of thinking https://en.wikiversity.org/wiki/Software_testing/History_of_testing
  • 5. No Tests Advantages 1. Time of development (developers are not writing tests) * 2. Cost of development (less time to develop features) * “I get paid for code that works, not for tests, so my philosophy is to test as little as possible...” Kent Beck (Stackoverflow) Disadvantages 1. Bugs… (at least, as long as developers are not “ninjas” that never create bugs) 2. Old bugs (nobody remembers/knows what a certain code does, why and so on) 3. Looking for the root cause is painful and time consuming 4. Many smaller bugs are hidden behind bigger bugs. 5. Interruptions in the current development process 6. Fear of changing code, since it could (and will) harm customers. Especially big changes/refactoring.
  • 6. Tests 1. Eliminate fear for changing code (increase developer confidence to change,fix and improve code) 2. Deliver better product to end point customers 3. Create de-facto “design by contract” for units, components, services and products 4. Decrease fix-bug life cycle by discovering bugs on early stages “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 (Stackoverflow)
  • 7. Tests Positive tests: implementing scenarios with valid input and verifying that received result is valid Negative tests: implementing scenarios with invalid input and verifying exceptions, errors and so on
  • 8. QA Only (End-to-End Tests) Advantages 1. Time of development (developers are not writing tests) * 2. Cost of development (less time to develop feature) * 3. Bugs don’t reach end point customer 4. Tests product as black box :) “I get paid for code that works, not for tests, so my philosophy is to test as little as possible...” Kent Beck (Stackoverflow) Disadvantages 1. The team completed their coding milestone a week/month/etc later (and worked a lot of overtime). 2. Looking for the root cause for a failing end-to-end test is painful and can take a long time. 3. Partner failures and lab failures ruin the test results continuously. 4. Many smaller bugs are hidden behind bigger bugs. 5. Tests are flaky at times. 6. Developers have to wait until the following day to know if a fix worked or not. 7. Interruptions in the current development process 8. Tests product as black box :( 9. Still Fear of changing code https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html
  • 9. Unit Tests Unit tests are short code fragments created by programmers to tests small units (methods, functions…). Ideally, each test case is independent from the others. Substitutes such as method stubs, mock objects, fakes, and test harnesses can be used to assist testing a module in isolation. Unit tests are typically written and run by software developers to ensure that code meets its design and behaves as intended. https://martinfowler.com/bliki/UnitTest.html https://en.wikipedia.org/wiki/Unit_testing
  • 10. Unit Tests ● Test each part of the program and show that the individual parts are correct. ● Test Execution is (should be) fast (Fast - when tests run slow, you won’t want to run them frequently - Uncle Bob) ● Can be executed at any time (Independent - you should be able to run each test independently and run the tests in any order and Repeatable - you should be able to run them in any environment - Uncle Bob) ● Kind of White Box Testing ● Unit Testing tests only the functionality of the units themselves and may not catch integration errors, or other system-wide issues ● Focus on behavior of a single module ● unit tests do not verify whether your code works with external dependencies correctly. ● usually executed by developer ● Looking for errors is easy ● Maintenance of unit test is (should be) cheap https://www.guru99.com/unit-test-vs-integration-test.html More about unit tests see at chapter 9 in Clean Code by Uncle Bob
  • 11. JUnit import java.util.*; public class Utils { public static <V> V deNull(V value, V defValue) { return Optional.ofNullable(value).orElse(defValue); } } Junit 5 <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> If we are using an IDE that is bundled with an older JUnit 5 version, it throws an exception when we try to run our unit tests by using our IDE. We can fix this problem by adding the following dependencies to our POM file: <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- if you want to run old junit4 tests, should --> <!-- add junit-vintage-engine dependency --> <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-launcher</artifactId> <version>${junit.platform.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-runner</artifactId> <version>${junit.platform.version}</version> <scope>test</scope> </dependency>
  • 12. JUnit unit tests import org.junit.jupiter.api.*; import java.util.*; import static org.assertj.core.api.Assertions.assertThat @ExtendWith(SpringExtension.class) class UtilsTest { @Nested @DisplayName("method: deNull") class DeNullTest { @Test @DisplayName("when method receives null and default is string, should return default value as string") void whenNullAndDefaultString_expectedDefStringValue() { assertThat(CollectionUtils.deNull(null, "else")) .isNotNull().isInstanceOf(String.class).isEqualTo("else"); } @Test @DisplayName("when method receives null and default is Integer, should return default Integer value") void whenNullAndDefaultInteger_expectedDefInetegerValue() { assertThat(CollectionUtils.deNull(null, new Integer(1))).isNotNull().isInstanceOf(Integer.class).isEqualTo(1); } @Test @DisplayName("when method receives null and default is primitive int, should return default Integer (wrapper) value") void whenNullAndDefaultPrimitiveInt_expectedDefInetegerValue() { assertThat(CollectionUtils.deNull(null, 1)).isNotNull().isInstanceOf(Integer.class).isEqualTo(1); } } }
  • 13. Component Tests Component - a logical unit which combines a number of classes according to some business logic Component testing is a method where testing of each component in an application is done separately. Component testing is also known as module, unit or program testing. It finds the defects in the module and verifies the functioning of software. Component tests can be large or small, according to how you define your components. The essence of the difference is that component tests deliberately neglect parts of the system outside the scope of the test. This is usually done by manipulating the system through internal code interfaces, using mocks and so on. https://sqa.stackexchange.com/questions/12630/what-is-component-testing-and-how-to-write-component-test-cases https://martinfowler.com/bliki/ComponentTest.html
  • 14. Component Tests In Spring-Boot (ver. 2.x, aka spring 5), Mockito (2.x) we have following tools for component tests: @SpyBean - Annotation that can be used to apply Mockito spies to a Spring ApplicationContext. Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner @MockBean - Annotation that can be used to add mocks to a Spring ApplicationContext. Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner @Captor (ArgumentCaptor) - Use it to capture argument values for further assertions in Mockito ArgumentMatcher - Allows creating customized argument matchers https://static.javadoc.io/org.mockito/mockito-core/2.19.1/index.html?org/mockito/Mockito.html https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-mocking-beans http://www.baeldung.com/mockito-annotations
  • 16. Clean Code 1. Treat your tests same as your code (well written, no duplications and so on) - https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882 2. Name/Structure convention: a. Names for your test methods should describe what a test does and what the expected result is. It helps to understand easier what is wrong when failure occurs. Example: withSomePrerequisite_whenSomeCondition_expectedSomeResult b. Test body should be short and easy to read (understand). If you have long preparation stage, move it into different method (e.g. setupTest() ). The second line is the action itself we want to test, and the last one - assertion (again, too many lines - move it to dedicated method). Rule of thumb for test body: 2-8 lines maximum. 3. Boy Scouts have a rule: “Always leave the campground cleaner than you found it”. Robert C. Martin (aka, Uncle Bob) re-phrased this rule so: “Always leave the code you’re editing a little bit better than before you found it” (https://cleancoders.com/). It’s relevant for tests, same as for your feature code.
  • 17. Nice Quotes from Dave Westerveld (https://twitter.com/offbeattesting/status/1019912503520735232?s=19) "The unit tests suck - we need to do integration testing." "These UI tests suck - we need to do unit testing" "BDD/TDD/*DD sucks - we need a different method" Conclusion: Writing bad tests is a problem that doesn't go away when you change where/how you write the tests Clean Code
  • 18. Public vs. Private (or Maintable tests) Now we live in the era when almost all people (developers) agree that it’s essentially important to write tests for our code. WOW—it’s (almost) a consensus. But now we have another question: how do we maintain tests and not tests maintain us? Let’s write tests for private methods (similar logic like components tests, and then mocking private tests with limit options, e.g. boolean private method mocked with only 3 options: true, false, exception. It’s possible with Powermock) As a result, it becomes difficult to make changes, because of a need to rewrite a lot of tests. Since we change implementation, we will spend a lot of time by rewriting tests, instead of add(new)/delete(unused)/etc tests. Conclusion: we want to interfere, as minimum as possible, in implementation details.
  • 19. Junit - Summary 1. Fast. Having a unit test suite that takes ages to run debases most of the advantages. The longer it takes to run, the more developers put off running tests until commit time, or start skipping them all together. 2. Isolated. It can be tempting to have a bunch of common set-up tasks used by multiple unit tests, but where possible, try to limit this. It ties unit tests together in ways that can be harder to isolate them in future. 3. Succinct. If your unit tests are hard to set up and complicated to write, it’s a good sign that the code you are trying to test is either too complex, or badly structured. Either way, it’s a good sign that a refactor might be required. 4. Easy to Understand. Good naming of unit tests is vital. You should be able to read a test name and understand what the test is testing, what results the test is expecting, and why it’s failing. Do not be afraid to make unit test names long – the more information the better. After all, you should only see them when they are failing. 5. Reliable. Tests shouldn’t be bound to a given environment or rely on external factors to work. They should work 100% of the time, or they are not going to fulfil their purpose.
  • 20. TDD Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: requirements are turned into very specific test cases, then the software is improved to pass the new tests only. This is opposed to software development that allows software to be added that is not proven to meet requirements. TDD is guiding us to develop code in more usable way (since the code is used by tests and we start from tests) Red-Green-Yellow approach Red - The development of every new feature should start with a failing test. Green - Enough production code should be written to make the test pass. Refactor - Improve the structure of the code to ease future changes and maintenance. http://www.giorgiosironi.com/2010/03/tdd-checklist-red-green-refactor-in.html https://en.wikipedia.org/wiki/Test-driven_development
  • 21. TDD Requirements Beer pub (credits to one of Wix meetups on a different subject where they introduced Beer Factory example): 1. Order Beer by type and can size 2. Check if in stock a. If yes - return Beer with price b. If no - return error Let’s try it :)
  • 22. Who tests the tester? Great, we wrote the tests, but who said they are good enough? We can run tests with coverage. It helps to check that we “have touched” all (or a lot of) lines in code. But… Do our tests check code or they are simply assertTrue(true). Do we need somebody to look into our tests? Definitely, yes - during the code review. Is it enough? No! At this stage, mutation tests could help us. Mutation Testing is a type of software testing where we mutate (change) certain statements in the source code and check if the test cases are able to find the errors (https://www.guru99.com/mutation-testing.html) Package for mutation tests in Java: http://pitest.org/
  • 23. Integration Tests 1. The idea behind Integration Testing is to combine modules in the application and test as a group to see that they are working fine 2. It is kind of Black Box Testing 3. It usually carried out after Unit Testing and before System Testing 4. Integrating testing may detect errors when modules are integrated to build the overall system 5. It pays attention to integration among modules 6. Integration tests verify that your code works with external dependencies correctly. 7. It is usually executed by QA team (update: more and more companies work with “NO QA” philosophy, so Integration Tests become the part of developer job) https://www.guru99.com/unit-test-vs-integration-test.html
  • 24. Confidence 1. Unit and Component Tests by developers (with coverage) 2. Mutation Tests 3. Code Review 4. CI (Continuous integration): running tests on every commit or merge to develop/master branch 5. Integration Tests by QA team 6. CD (Continuous delivery) - running tests nightly 7. Automation during all stages 8. Stress and Load Tests (dedicated QA team) 9. Chaos Monkey on QA, Staging, Production environments (https://github.com/Netflix/SimianArmy/wiki/Chaos-Monkey) and for spring-boot: https://codecentric.github.io/chaos-monkey-spring-boot/ Fast delivery and new high-quality features Confidence to make changes and introduce new technologies Reducing ping-pong between Developers and QA teams (and Support team) When you develop your code - make it testable (for e.g. TDD makes it easier, since you start from writing tests)
  • 25. Thank You https://github.com/grinfeld/beerpub https://en.wikiversity.org/wiki/Software_testing/History_of_testing https://en.wikipedia.org/wiki/Extreme_programming#Origins http://agilemanifesto.org https://twitter.com/KentBeck https://stackoverflow.com/questions/153234/how-deep-are-your-unit-tests?answertab=oldest#tab-top https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html https://martinfowler.com/bliki/UnitTest.html https://en.wikipedia.org/wiki/Unit_testing https://www.guru99.com/unit-test-vs-integration-test.html https://sqa.stackexchange.com/questions/12630/what-is-component-testing-and-how-to-write-component-test-cases https://martinfowler.com/bliki/ComponentTest.html http://www.baeldung.com/mockito-annotations https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-mocking-beans https://static.javadoc.io/org.mockito/mockito-core/2.19.1/index.html?org/mockito/Mockito.html Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882 https://twitter.com/unclebobmartin https://cleancoders.com/ https://en.wikipedia.org/wiki/Test-driven_development http://www.giorgiosironi.com/2010/03/tdd-checklist-red-green-refactor-in.html https://github.com/Netflix/SimianArmy/wiki/Chaos-Monkey) https://dzone.com/articles/spring-di-patterns-the-good-the-bad-and-the-ugly https://github.com/powermock/powermock https://www.guru99.com/mutation-testing.html http://pitest.org/ https://twitter.com/offbeattesting/status/1019912503520735232?s=19 https://manifesto.co.uk/unit-testing-best-practices-java/ https://codecentric.github.io/chaos-monkey-spring-boot/

Editor's Notes

  • #7: Uncle Bob: leave the ground cleaner then it has been before What is Component ? Missing load, stress tests
  • #8: Design by contract
  • #9: In case QA have full coverage (ha,ha,ha) QA will come to me (open) next month a lot of bugs.
  • #11: We want to run tests on every commit. If you run tests and need to wait hours for results...
  • #13: @autowired only via constructor: 1. since if we don't want to use SpringTest (because it increases time of running tests), how we mock annotated variables 2. DI means dependencies injected only public API 3. Every time you use @Autowired over private field, you kill tests 4. when using constructor injection and you see a lot of arguments in constructor, means something is wrong with your structure
  • #15: Explain what is Spy and Mock
  • #16: The first example is faster since it starts less spring staff Actually “whenValidId_expectedReturnValidUser” is the bad test - it tests Mockito and not the code
  • #17: Consider, your time limitations for item 3
  • #19: interfaces in component tests in contrast to private methods is less invasive, since we hide implementation behind the interface. If we want to change implementation, usually the contract stays the same, or some parameter is added or removed, which could be solved with refactoring tools in any IDE in nowdays
  • #20: Story: no tests - started to write down how much time it took to maintain bugs from support -> delays in delivery hired QA automation: only qa tests -> less bugs in production, but still a lot of interruptions, but now from QA (bug life-cycle still rather long) unit tests (and qa tests) -> most bugs found during developing process, so less interruption and less bugs reach production everything automated till manual tests, dedicated environment for tests during progression -> less afford from developers and QA Define minimalistic scope and test it Use mocks instead of real data integration Minimum framework. If you can write test without Spring - do it Should be fast. Very fast! Execute tests (old and new) every time you close some functionality (and at least once a day. More is better) Name convention. You and others should understand what is going on in case of failure Succinct (краткий). Reliable (надежный).
  • #23: When I want to test complicated assertion, I go to source code and change it, run test and expect it fails. It’s not enough.