SlideShare a Scribd company logo
1 of 105
Download to read offline
kgolev.com@kotseto
Test Code
Kostadin Golev
CTO @ Rewards Labs
That will not slow you down
kgolev.com@kotseto
kgolev.com@kotseto
Tests? Who’s got time for that?
What do we have time for, anyway?
kgolev.com@kotseto
How do programmers actually
spend their time?
kgolev.com@kotseto
What programmers actually do
Understand
70%
Change
25%
Write
5%
LInk: http://blogs.msdn.com/b/peterhal/archive/2006/01/04/509302.aspx
kgolev.com@kotseto
Is this real?
Let’s verify!
kgolev.com@kotseto
What is your ideal
programming day?
kgolev.com@kotseto
How many of those days
do you get?
And how often you chase a bug for hours?
kgolev.com@kotseto
One day of work is replicated in
less than one hour
What happens in the other 7+ hours?
kgolev.com@kotseto
kgolev.com@kotseto
Can an understanding be:
• executed?
• shared?
• scaled?
kgolev.com@kotseto
How do you call an understanding that is:
• concrete
• small
• executable
• shareable
• scalable
kgolev.com@kotseto
How do you call an understanding that is:
• concrete
• small
• executable
• shareable
• scalable
we call it
a TEST
kgolev.com@kotseto
What would you automate?
Understand
70%
Change
25%
Write
5%
LInk: http://blogs.msdn.com/b/peterhal/archive/2006/01/04/509302.aspx
kgolev.com@kotseto
A test is an understanding of
the system
Understands, so you do not have to!
You can even verify it by execution
kgolev.com@kotseto
A test is not an understanding
of the system implementation
Why do double work?
kgolev.com@kotseto
For all this to work a test must
be trusted
kgolev.com@kotseto
How do you put understanding
into your tests?
How do you translate between AbstractSingletonProxyRegistrationFactoryTest
fails and “Register with Facebook is broken”?
kgolev.com@kotseto
@Test
void testRegistration() {
// Arrange | Given
UsersRepo usersRepo = Mockito.mock(UsersRepo.class);
Users users = new Users(usersRepo);
UserRequest userRequest =
new UserRequest(null, "john.doe@somemail.com", "John", "", "Doe", "asdf", null, null, 5.0);
Mockito.when(usersRepo.createUser(userRequest)).thenReturn(5);
// Act | When
UserRequestResult result = users.register(userRequest);
// Assert | Then
assertTrue(result.isSuccessful());
assertEquals(5, result.getUserId());
}
kgolev.com@kotseto
@Test
void testRegistration() {
// Arrange | Given
UsersRepo usersRepo = Mockito.mock(UsersRepo.class);
Users users = new Users(usersRepo);
UserRequest userRequest =
new UserRequest(null, "john.doe@somemail.com", "John", "", "Doe", "asdf", null, null, 5.0);
Mockito.when(usersRepo.createUser(userRequest)).thenReturn(5);
// Act | When
UserRequestResult result = users.register(userRequest);
// Assert | Then
assertTrue(result.isSuccessful());
assertEquals(5, result.getUserId());
}
Assert
Act
Arrange
Name
kgolev.com@kotseto
@Test
void testRegistration() {
// Arrange | Given
UsersRepo usersRepo = Mockito.mock(UsersRepo.class);
Users users = new Users(usersRepo);
UserRequest userRequest =
new UserRequest(null, "john.doe@somemail.com", "John", "", "Doe", "asdf", null, null, 5.0);
Mockito.when(usersRepo.createUser(userRequest)).thenReturn(5);
// Act | When
UserRequestResult result = users.register(userRequest);
// Assert | Then
assertTrue(result.isSuccessful());
assertEquals(5, result.getUserId());
}
kgolev.com@kotseto
testRegistration?
registration_withMandatoryFields_isSuccessful
kgolev.com@kotseto
whatWeTest_whenCondition_doesThat
registration_withMandatoryFields_isSuccessful
kgolev.com@kotseto
whatWeTest_whenCondition_doesThat
registration_withMandatoryFields_isSuccessful
registration_withFacebook_isSuccessful
registration_withMissingEmail_returnsError
kgolev.com@kotseto
What is easier to read?
kgolev.com@kotseto
@DisplayName
kgolev.com@kotseto
@DisplayName("Registration with mandatory fields ✅")
@Test
void registration_withMandatoryFields_isSuccessful() {
}
kgolev.com@kotseto
Or even:
kgolev.com@kotseto
Also on the JVM:
Spock (Groovy)
Spek (Kotlin)
ScalaTest (Scala)
kgolev.com@kotseto
class UsersTest: Spek ({
describe("users") {
Users users = new Users(...
it("should register with mandatory fields") {
...
}
it("should fail with email missing") {
...
}
}
})
kgolev.com@kotseto
describe("users") {
…
it("should register with mandatory fields") {
...
}
Describe what
kgolev.com@kotseto
What about assertions?
kgolev.com@kotseto
junit.framework.AssertionFailedError
at junit.framework.Assert.fail(Assert.java:55)
at junit.framework.Assert.assertTrue(Assert.java:22)
at junit.framework.Assert.assertTrue(Assert.java:31)
at junit.framework.TestCase.assertTrue(TestCase.java:201)
What?
kgolev.com@kotseto
junit.framework.AssertionFailedError: registration should be successful
…
Better now?
kgolev.com@kotseto
assertTrue(“registration should be successful", true);
junit.framework.AssertionFailedError: registration should be successful
…
kgolev.com@kotseto
assertEquals(5, result.getUserId(), "id for the created user should be returned”);
org.opentest4j.AssertionFailedError: id for the created user should be returned ==>
Expected :4
Actual :5
kgolev.com@kotseto
// Arrange | Given
…
UserRequest userRequest =
new UserRequest(null, "john.doe@somemail.com",
"John", "", "Doe", "asdf", null, null, 5.0);
…
// Act | When
// Assert | Then
What about these?
kgolev.com@kotseto
// Arrange | Given
…
UserRequest userRequest = …
when(usersRepo.createUser(userRequest)).thenReturn(5);
// Act | When
// Assert | Then
assertEquals(5, result.getUserId());
Or these?
kgolev.com@kotseto
// Arrange | Given
…
UserRequest userRequest = …
when(usersRepo.createUser(userRequest)).thenReturn(USER_ID);
// Act | When
// Assert | Then
assertEquals(USER_ID, result.getUserId());
No Magic
kgolev.com@kotseto
// Arrange | Given
…
UserRequest userRequest =
new UserRequest(NO_AUTH_TOKEN, EMAIL, FIRST_NAME,
NO_MID_NAME, LAST_NAME, PASSWORD_HASH, NO_PHONE,
NO_ADDRESS, SIGN_UP_BONUS);
…
// Act | When
// Assert | Then
No Magic
kgolev.com@kotseto
UserRequest userRequestWithMandatoryParameters =
new UserRequest(EMAIL, FIRST_NAME, LAST_NAME,
PASSWORD_HASH, SIGN_UP_BONUS);
// Or just a method?
Wasn’t this register_withMandatoryParameters?
kgolev.com@kotseto
Remove noise
kgolev.com@kotseto
assertTrue(result.isSuccessful());
assertEquals(USER_ID, result.getUserId());
UserRequestResult expected =
new UserRequestResult(SUCCESSFUL, USER_ID);
assertEquals(expected, actual);
Remove noise
kgolev.com@kotseto
Mockito.verify(userRepo).createUser(userRequest);
assertNotNull(actual);
assertEquals(expected, actual);
Mockito.verifyNoMoreInteractions(userRepo);
Mockito.verifyZeroInteractions(otherDependency);
Remove noise
kgolev.com@kotseto
Assert one thing, in one test
Do not assert the same thing in different tests
No “let’s be on the safe side”
kgolev.com@kotseto
Your tests will fail. Make them
easy to read and understand
When in doubt, prefer more verbose/readable test code
It will save you tons of time
kgolev.com@kotseto
10% optimisation
Saved time
7%
Understand
63%
Change
25%
Write
5%
LInk: http://blogs.msdn.com/b/peterhal/archive/2006/01/04/509302.aspx
kgolev.com@kotseto
Is it free?
More tests == more code
kgolev.com@kotseto
A test should be an understanding of your
system behaviour
A test should not be an understanding of
your system implementation
kgolev.com@kotseto
The best place to understand
your production code is your
production code
Tests that know about your implementation details are
double work
kgolev.com@kotseto
When you change the
implementation the test will fail
Behaviour stayed the same
kgolev.com@kotseto
A test needs to know what?
DANGER ZONE
kgolev.com@kotseto
UserRequestResult register(UserRequest userRequest) {
// some validation here
int userId = usersRepo.createUser(userRequest);
return new UserRequestResult(userId);
}
Let’s look inside
kgolev.com@kotseto
// make sure userRepo returns some userId for given parameters
Mockito.when(usersRepo.createUser(userRequest)).thenReturn(USER_ID);
// execute what we want to test
UserRequestResult actual = users.register(userRequest);
// verify call to userRepo was OK
Mockito.verify(usersRepo).createUser(userRequest);
// construct expected UserRequestResult
UserRequestResult expected = new UserRequestResult(SUCCESSFUL,
USER_ID);
// assert expected is the same as the actual
assertEquals(expected, actual);
Let’s Follow The Path
kgolev.com@kotseto
// make sure userRepo returns some userId for given parameters
Mockito.when(usersRepo.createUser(userRequest)).thenReturn(USER_ID);
// execute what we want to test
UserRequestResult actual = users.register(userRequest);
// verify call to userRepo was OK
Mockito.verify(usersRepo).createUser(userRequest);
// construct expected UserRequestResult
UserRequestResult expected = new UserRequestResult(SUCCESSFUL,
USER_ID);
// assert expected is the same as the actual
assertEquals(expected, actual);
Let’s Follow The Path
kgolev.com@kotseto
// make sure userRepo returns some userId for given parameters
Mockito.when(usersRepo.createUser(userRequest)).thenReturn(USER_ID);
// execute what we want to test
UserRequestResult actual = users.register(userRequest);
// verify call to userRepo was OK
Mockito.verify(usersRepo).createUser(userRequest);
// construct expected UserRequestResult
UserRequestResult expected = new UserRequestResult(SUCCESSFUL,
USER_ID);
// assert expected is the same as the actual
assertEquals(expected, actual);
Let’s Follow The Path
kgolev.com@kotseto
// make sure userRepo returns some userId for given parameters
Mockito.when(usersRepo.createUser(userRequest)).thenReturn(USER_ID);
// execute what we want to test
UserRequestResult actual = users.register(userRequest);
// verify call to userRepo was OK
Mockito.verify(usersRepo).createUser(userRequest);
// construct expected UserRequestResult
UserRequestResult expected =
new UserRequestResult(SUCCESSFUL, USER_ID);
// assert expected is the same as the actual
assertEquals(expected, actual);
Let’s Follow The Path
kgolev.com@kotseto
Test should not verify your
implementation path
kgolev.com@kotseto
// make sure userRepo returns some userId for given parameters
Mockito.when(usersRepo.createUser(userRequest)).thenReturn(USER_ID);
// execute what we want to test
UserRequestResult actual = users.register(userRequest);
// verify call to userRepo was OK
Mockito.verify(usersRepo).createUser(userRequest);
// construct expected UserRequestResult
UserRequestResult expected = new UserRequestResult(SUCCESSFUL,
USER_ID);
// assert expected is the same as the actual
assertEquals(expected, actual);
Do you need that?
kgolev.com@kotseto
Do not use verify() if
you do not really need it
Use Mock Object judiciously by Daniela Kolarova
https://dzone.com/articles/use-mock-objects-judiciously
kgolev.com@kotseto
Try writing the test first
no implementation -> no implementation details!
kgolev.com@kotseto
Implementation dependency
cannot be avoided completely
Your
code
Intention Implementation
kgolev.com@kotseto
Can we ease the pain?
Let’s see how
kgolev.com@kotseto
kgolev.com@kotseto
kgolev.com@kotseto
kgolev.com@kotseto
Tests are often a tree
How does that help?
kgolev.com@kotseto
We change UsersRepo class
kgolev.com@kotseto
We change UsersRepo class
why so many changes in UsersTest?
2 lines production code
9 lines of test code!
kgolev.com@kotseto
@DisplayName("Users registration")
class UsersTest {
@Test
void whenUserDoesNotExist_withMandatory_shouldSucceed() {}
@Test
void whenUserDoesNotExist_withSignUpBonus_should_assign_it() {}
@Test
void whenUserDoesNotExist_whenRegisteredWithFacebook_shouldRecordThat() {}
@Test
void whenUserExists_shouldReturnAlreadyRegistered () {}
kgolev.com@kotseto
@Nested
Less code to maintain, easier to read and understand
kgolev.com@kotseto
@DisplayName("Users registration")
class UsersTest {
@Nested
@DisplayName("when user does not exist")
class whenUserDoesNotExists {
@Test
void withMandatory_shouldSucceed() {}
@Test
void withSignUpBonus_should_assign_it() {}
@Test
void whenRegisteredWithFacebook_shouldRecordThat() {}
}
@Test
void whenUserExists_shouldReturnAlreadyRegistered () {}
kgolev.com@kotseto
@DisplayName("Users registration")
class UsersTest {
private UsersRepo usersRepo;
private Users users;
@BeforeEach // <- executed first
void setUp() {
usersRepo = mock(UsersRepo.class);
users = new Users(usersRepo);
}
@DisplayName("when user does not exist")
@Nested
class whenUserDoesNotExists {
@BeforeEach // <- executed second
void setUp() {}
kgolev.com@kotseto
Place for all common setup
kgolev.com@kotseto
@BeforeEach
void setUp() { … }
@DisplayName("when user does not exist")
@Nested
class whenUserDoesNotExists {
@BeforeEach
void setUpUserDoesNotExist() { … }
@Test
void whenUserDoesNotExists_withMandatory_shouldSucceed() {
UserRequest userRequest = …;
UserRequestResult actual = users.register(userRequest);
UserRequestResult expected = …;
assertEquals(expected, actual);
}
Much simpler arrange | given now
kgolev.com@kotseto
If we make the same change again
2 lines production code
5 lines (from 9) of test code
kgolev.com@kotseto
@RunWith(HierarchicalContextRunner.class)
Requires JUnit 4.12

Cannot be combined with other runner
IDE support limited compared to JUnit 5
kgolev.com@kotseto
What about UsersRepoTest?
Can we ease the pain there as well?
kgolev.com@kotseto
What if code we test is a pure
function?
How about some email validation?
kgolev.com@kotseto
john.doe@gmail.com
@gmail.com
john@doe@mail@com
john.@mail@com
john.doe@mail.co.uk
kgolev.com@kotseto
@Test
public void validEmail_isValid() {
boolean isValid =
emailValidation.isValid("john.doe@gmail.com");
assertTrue(isValid);
}
@Test
public void missingUsername_isNotValid() {
boolean isValid = emailValidation.isValid("@gmail.com");
assertTrue(!isValid);
}
…
// 3 similar tests here
kgolev.com@kotseto
public void mailValidation(String email, boolean expected) {
boolean actual = emailValidation.isValid(email);
assertEquals(expected, actual);
}
What we actually need
kgolev.com@kotseto
public void mailValidation(String email, boolean expected) {
boolean actual = emailValidation.isValid(email);
assertEquals(expected, actual);
}
Why not just call it from our tests?
Still have to maintain all those one liner tests
kgolev.com@kotseto
@RunWith(Parameterized.class)
public class EmailValidationTest {
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{ "john.doe@gmail.com", true},
{ "@gmail.com", false },
{ "john@doe@mail@com", true },
{ "john.@mail@com", false },
{ "john.doe@mail.co.uk", true }
});
}
@Parameterized.Parameter(0)
public String email;
@Parameterized.Parameter(1)
public boolean expected;
kgolev.com@kotseto
@Test
public void mailValidation() {
boolean actual = emailValidation.isValid(email);
assertEquals(expected, actual);
}
After this setup we can write
kgolev.com@kotseto
@ParameterizedTest
@ValueSource(strings = {
"john.doe@gmail.com",
"john.doe@mail.co.uk" })
void validEmails_areValid(String email) {
assertEquals(VALID, emailValidation.isValid(email));
}
kgolev.com@kotseto
enum Status {
OK, INVALID_NAME, INVALID_DATE, …
}
@ParameterizedTest
@EnumSource(value = Status.class, mode = EXCLUDE, names = “OK")
void whenNotOK_shouldReturnError(Status status) {
…
Other ways to provide parameters
Or get them from a method or even csv
kgolev.com@kotseto
@Annotations
@Unstopable
@Progress
annotationmania.com
kgolev.com@kotseto
describe("Email validation") {
val emailValidation = EmailValidation();
listOf(
"john.doe@gmail.com",
"john@mail.co.uk"
).forEach { email ->
describe("validating email $email") {
it("is valid") {
assertTrue(emailValidation.isValid(email))
}
}
}
}
kgolev.com@kotseto
listOf(
"john.doe@gmail.com",
"john@mail.co.uk"
).forEach { email ->
describe("validating email $email") {
it("is valid") {}
}
}
}
kgolev.com@kotseto
Also great: Spock for Groovy
kgolev.com@kotseto
Does this solve the problem?
2 lines production code
3 lines of test code
kgolev.com@kotseto
Nested and Parameterized tests
Less code to maintain and understand
Faster development
kgolev.com@kotseto
How do you make tests that
you trust?
Isn’t easy to understand and maintain enough already?
kgolev.com@kotseto
“All Models are wrong, some are useful” — George Box
source: https://martinfowler.com/articles/practical-test-pyramid.html
kgolev.com@kotseto
Small tests - small problems
Like children
kgolev.com@kotseto
Why we need higher level tests
source: https://chriskottom.com/
kgolev.com@kotseto
The higher you go,
the harder to know where the
problem is
For every high level test that fails, there should be a
lower level one that also fails and points at the issue
kgolev.com@kotseto
If you find a bug with a higher level test
Write a smaller unit one, so you know where to focus
immediately next time
kgolev.com@kotseto
Let’s wrap it up
kgolev.com@kotseto
Automate your understanding
kgolev.com@kotseto
Automate your understanding
Not your implementation details
kgolev.com@kotseto
Automate your understanding
Not your implementation details
Automate at the lowest possible level
kgolev.com@kotseto
Questions?
kgolev.com/talks/automate-your-understanding
kgolev.com@kotseto
This was my understanding
Thank you!
kgolev.com/talks/automate-your-understanding

More Related Content

What's hot

Rifartek Robot Training Course - How to use ClientRobot
Rifartek Robot Training Course - How to use ClientRobotRifartek Robot Training Course - How to use ClientRobot
Rifartek Robot Training Course - How to use ClientRobot
Tsai Tsung-Yi
 
10reasons
10reasons10reasons
10reasons
Li Huan
 
20111018 boost and gtest
20111018 boost and gtest20111018 boost and gtest
20111018 boost and gtest
Will Shen
 
Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummies
Harry Potter
 

What's hot (20)

DevSecOps for Developers, How To Start (ETC 2020)
DevSecOps for Developers, How To Start (ETC 2020)DevSecOps for Developers, How To Start (ETC 2020)
DevSecOps for Developers, How To Start (ETC 2020)
 
RPG Program for Unit Testing RPG
RPG Program for Unit Testing RPG RPG Program for Unit Testing RPG
RPG Program for Unit Testing RPG
 
軟體測試是在測試什麼?
軟體測試是在測試什麼?軟體測試是在測試什麼?
軟體測試是在測試什麼?
 
RoboSpock Poznań ADG 2016
RoboSpock Poznań ADG 2016RoboSpock Poznań ADG 2016
RoboSpock Poznań ADG 2016
 
Test Gap Analysis and regression minimization with Drill4j. Observability on ...
Test Gap Analysis and regression minimization with Drill4j. Observability on ...Test Gap Analysis and regression minimization with Drill4j. Observability on ...
Test Gap Analysis and regression minimization with Drill4j. Observability on ...
 
It's always your fault. Poznań ADG 2016
It's always your fault. Poznań ADG 2016It's always your fault. Poznań ADG 2016
It's always your fault. Poznań ADG 2016
 
Trying to build an Open Source browser in 2020
Trying to build an Open Source browser in 2020Trying to build an Open Source browser in 2020
Trying to build an Open Source browser in 2020
 
Rifartek Robot Training Course - How to use ClientRobot
Rifartek Robot Training Course - How to use ClientRobotRifartek Robot Training Course - How to use ClientRobot
Rifartek Robot Training Course - How to use ClientRobot
 
Developing in the Fastlane -> How LookLive uses Fastlane to automate and spee...
Developing in the Fastlane -> How LookLive uses Fastlane to automate and spee...Developing in the Fastlane -> How LookLive uses Fastlane to automate and spee...
Developing in the Fastlane -> How LookLive uses Fastlane to automate and spee...
 
10reasons
10reasons10reasons
10reasons
 
Google C++ Testing Framework in Visual Studio 2008
Google C++ Testing Framework in Visual Studio 2008Google C++ Testing Framework in Visual Studio 2008
Google C++ Testing Framework in Visual Studio 2008
 
Automated testing in Python and beyond
Automated testing in Python and beyondAutomated testing in Python and beyond
Automated testing in Python and beyond
 
Reading Other Peoples Code (NDC Copenhagen 2019)
Reading Other Peoples Code (NDC Copenhagen 2019)Reading Other Peoples Code (NDC Copenhagen 2019)
Reading Other Peoples Code (NDC Copenhagen 2019)
 
Modern Python Testing
Modern Python TestingModern Python Testing
Modern Python Testing
 
20111018 boost and gtest
20111018 boost and gtest20111018 boost and gtest
20111018 boost and gtest
 
Seeding a Tree in a Gherkin
Seeding a Tree in a GherkinSeeding a Tree in a Gherkin
Seeding a Tree in a Gherkin
 
iOS Unit Testing
iOS Unit TestingiOS Unit Testing
iOS Unit Testing
 
Quality of life through Unit Testing
Quality of life through Unit TestingQuality of life through Unit Testing
Quality of life through Unit Testing
 
Testing without assertions - #HUSTEF2019
Testing without assertions - #HUSTEF2019Testing without assertions - #HUSTEF2019
Testing without assertions - #HUSTEF2019
 
Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummies
 

Similar to Test code that will not slow you down

Acceptance & Functional Testing with Codeception - Devspace 2015
Acceptance & Functional Testing with Codeception - Devspace 2015 Acceptance & Functional Testing with Codeception - Devspace 2015
Acceptance & Functional Testing with Codeception - Devspace 2015
Joe Ferguson
 
5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniter5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniter
nicdev
 

Similar to Test code that will not slow you down (20)

Code Quality Practice and Tools
Code Quality Practice and ToolsCode Quality Practice and Tools
Code Quality Practice and Tools
 
Java Script Isn\'t a Toy Anymore
Java Script Isn\'t a Toy AnymoreJava Script Isn\'t a Toy Anymore
Java Script Isn\'t a Toy Anymore
 
Bridging the communication Gap & Continuous Delivery
Bridging the communication Gap & Continuous DeliveryBridging the communication Gap & Continuous Delivery
Bridging the communication Gap & Continuous Delivery
 
Why test with flex unit
Why test with flex unitWhy test with flex unit
Why test with flex unit
 
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
 
You Know WebOS
You Know WebOSYou Know WebOS
You Know WebOS
 
Android the Agile way
Android the Agile wayAndroid the Agile way
Android the Agile way
 
Swift meetup22june2015
Swift meetup22june2015Swift meetup22june2015
Swift meetup22june2015
 
An Introduction To CQRS
An Introduction To CQRSAn Introduction To CQRS
An Introduction To CQRS
 
Alternate for scheduled apex using flow builder
Alternate for scheduled apex using flow builderAlternate for scheduled apex using flow builder
Alternate for scheduled apex using flow builder
 
Testing with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs LifeTesting with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs Life
 
Metrics by coda hale : to know your app’ health
Metrics by coda hale : to know your app’ healthMetrics by coda hale : to know your app’ health
Metrics by coda hale : to know your app’ health
 
Acceptance & Functional Testing with Codeception - Devspace 2015
Acceptance & Functional Testing with Codeception - Devspace 2015 Acceptance & Functional Testing with Codeception - Devspace 2015
Acceptance & Functional Testing with Codeception - Devspace 2015
 
Acceptance & Functional Testing with Codeception - SunshinePHP 2016
Acceptance & Functional Testing with Codeception - SunshinePHP 2016Acceptance & Functional Testing with Codeception - SunshinePHP 2016
Acceptance & Functional Testing with Codeception - SunshinePHP 2016
 
5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniter5 Reasons To Love CodeIgniter
5 Reasons To Love CodeIgniter
 
Building a Kubernetes Powered Central Go Modules Repository
Building a Kubernetes Powered Central Go Modules RepositoryBuilding a Kubernetes Powered Central Go Modules Repository
Building a Kubernetes Powered Central Go Modules Repository
 
Adopting F# at SBTech
Adopting F# at SBTechAdopting F# at SBTech
Adopting F# at SBTech
 
Writing Commits for You, Your Friends, and Your Future Self
Writing Commits for You, Your Friends, and Your Future SelfWriting Commits for You, Your Friends, and Your Future Self
Writing Commits for You, Your Friends, and Your Future Self
 
1 aleksandr gritsevski - attd example using
1   aleksandr gritsevski - attd example using1   aleksandr gritsevski - attd example using
1 aleksandr gritsevski - attd example using
 
Birmingham JUG Lightweight Microservices with Microprofile and Raspberry PIs
Birmingham JUG Lightweight Microservices with Microprofile and Raspberry PIsBirmingham JUG Lightweight Microservices with Microprofile and Raspberry PIs
Birmingham JUG Lightweight Microservices with Microprofile and Raspberry PIs
 

Recently uploaded

JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
Max Lee
 
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdfMastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
mbmh111980
 

Recently uploaded (20)

JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
 
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdf
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdfStrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdf
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdf
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024
 
A Guideline to Zendesk to Re:amaze Data Migration
A Guideline to Zendesk to Re:amaze Data MigrationA Guideline to Zendesk to Re:amaze Data Migration
A Guideline to Zendesk to Re:amaze Data Migration
 
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
Abortion ^Clinic ^%[+971588192166''] Abortion Pill Al Ain (?@?) Abortion Pill...
 
AI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning FrameworkAI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning Framework
 
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
 
how-to-download-files-safely-from-the-internet.pdf
how-to-download-files-safely-from-the-internet.pdfhow-to-download-files-safely-from-the-internet.pdf
how-to-download-files-safely-from-the-internet.pdf
 
APVP,apvp apvp High quality supplier safe spot transport, 98% purity
APVP,apvp apvp High quality supplier safe spot transport, 98% purityAPVP,apvp apvp High quality supplier safe spot transport, 98% purity
APVP,apvp apvp High quality supplier safe spot transport, 98% purity
 
How to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabberHow to install and activate eGrabber JobGrabber
How to install and activate eGrabber JobGrabber
 
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product UpdatesGraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
 
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
 
What need to be mastered as AI-Powered Java Developers
What need to be mastered as AI-Powered Java DevelopersWhat need to be mastered as AI-Powered Java Developers
What need to be mastered as AI-Powered Java Developers
 
Workforce Efficiency with Employee Time Tracking Software.pdf
Workforce Efficiency with Employee Time Tracking Software.pdfWorkforce Efficiency with Employee Time Tracking Software.pdf
Workforce Efficiency with Employee Time Tracking Software.pdf
 
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdfMastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
 
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
 
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAGAI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
 
OpenChain @ LF Japan Executive Briefing - May 2024
OpenChain @ LF Japan Executive Briefing - May 2024OpenChain @ LF Japan Executive Briefing - May 2024
OpenChain @ LF Japan Executive Briefing - May 2024
 
INGKA DIGITAL: Linked Metadata by Design
INGKA DIGITAL: Linked Metadata by DesignINGKA DIGITAL: Linked Metadata by Design
INGKA DIGITAL: Linked Metadata by Design
 

Test code that will not slow you down