SlideShare a Scribd company logo
1 of 52
Download to read offline
Testing For Unicorns
From Unit to Deployment Tests
Alex Soto

@alexsotob
@alexsotob2
Alex Soto
Red Hat Engineer
www.lordofthejars.com
@alexsotob
Who Am I?
@alexsotob3
Questions
@alexsotob4
Click to add subtitle
ASSERTIONS
@alexsotob
JUnit Test
@Test
public void should_find_composer_by_name() {
// Given:
Composers composers = new Composers();
// When:
final Composer mozart = composers.findComposerByName("Wolfgang Amadeus Mozart");
// Then:
assertEquals("Wolfgang Amadeus Mozart", mozart.getName());
assertEquals(Era.CLASSICAL, mozart.getEra());
assertEquals(LocalDate.of(1756, 1, 27), mozart.getBirthdate());
assertEquals(LocalDate.of(1791, 12, 5), mozart.getDied());
}
5
Readable name
BDD style
AssertEquals Order
Depends On Equals
@alexsotob6
AssertJ
@alexsotob
AssertJ Test
import static org.assertj.core.api.Assertions.assertThat;
@Test
public void should_find_composer_by_name() {
// Given:
Composers composers = new Composers();
// When:
final Composer mozart = composers.findComposerByName("Wolfgang Amadeus Mozart”);
// Then:
assertThat(mozart.getName()).isEqualTo("Wolfgang Amadeus Mozart”);
assertThat(mozart).returns("Wolfgang Amadeus Mozart", Composer::getName);
assertThat(mozart.getBirthdate()).isEqualTo(LocalDate.of(1756, 1, 27));
assertThat(mozart).isEqualToComparingFieldByField(expectedMozart);
assertThat(mozart).isEqualToIgnoringNullFields(expectedMozart);
}
7
Static Import
Readable Assertions
Not Depending on
Equals
@alexsotob
AssertJ Test Collections
@Test
public void should_find_operas_by_composer_name() {
// Given:
Composers composers = new Composers();
// When:
final List<Opera> operas = composers.findOperasByComposerName("Wolfgang Amadeus Mozart");
// Then:
assertThat(operas)
.hasSize(2)
.extracting(Opera::getName)
.containsExactlyInAnyOrder("Die Zauberflöte", "Don Giovanni”);
}
8
Train Call (IDE
support) Create List with
getName Result
Methods for String
@alexsotob
AssertJ Soft Assertions
@Test
public void should_find_composer_by_name_soft_assertions() {
// Given:
Composers composers = new Composers();
// When:
final Composer mozart = composers.findComposerByName("Wolfgang Amadeus Mozart");
// Then:
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(mozart.getName()).isEqualTo("Wolfgang Amadeus Mozart");
softly.assertThat(mozart.getEra()).isEqualTo(Era.CLASSICAL);
softly.assertThat(mozart.getBirthdate()).isEqualTo(LocalDate.of(1756, 1, 27));
softly.assertThat(mozart.getDied()).isEqualTo(LocalDate.of(1791, 12, 5));
});
}
9
Java 8 Lambda
All assertions in Block
@alexsotob10
Things go
Wrong
@alexsotob
Try/Catch
@Test
public void should_throw_exception_if_composer_not_found() {
// Given:
Composers composers = new Composers();
// When:
try {
final Composer salieri = composers.findComposerByName("Antonio Salieri");
fail();
} catch (IllegalArgumentException e) {
// Then:
assertEquals("Composer Antonio Salieri is not found", e.getMessage());
}
}
11
Fails if Success
@alexsotob
JUnit
@Test(expected = IllegalArgumentException.class)
public void should_throw_exception_if_composer_not_found_version_2() {
// Given:
Composers composers = new Composers();
// When:
final Composer salieri = composers.findComposerByName("Antonio Salieri");
}
12
Special Attribute
@alexsotob
AssertJ Exceptions
@Test
public void should_throw_exception_if_composer_not_found_version_3() {
// Given:
Composers composers = new Composers();
// When:
Throwable thrown = catchThrowable(() -> composers.findComposerByName("Antonio Salieri"));
// Then:
assertThat(thrown).isInstanceOf(IllegalArgumentException.class)
.withFailMessage("Composer Antonio Salieri is not found”);
}
13
Catch Exception of Lambda
Assertion Methods for
Exceptions
@alexsotob
IDE Friendly
Ctrl + Space works
Assertions Generation
ComposerAssert.assertThat(mozart).hasName(“Mozart”).hasBirthdate(LocalDate.of(..);
Out-of-the-Box Assertions
Guava, Joda, DB, Neo4j and Swing
Benefits of AssertJ
14
@alexsotob15
Don’t Sleep, Just Wait
@alexsotob
Asynchronous Call
@Test
public void should_play_operas() throws InterruptedException {
// Given:
final Opera nozzeDiFigaro = ...;
Gramophone gramophone = new Gramophone();
// When:
gramophone.play(nozzeDiFigaro);
// Then:
TimeUnit.SECONDS.sleep(3);
assertThat(gramophone.getCurrentOpera()).isEqualTo(nozzeDiFigaro);
}
16
Asynchronous Call
Slowest Machine Time
@alexsotob17
@alexsotob
Awaitility Example
@Test
public void should_play_operas_version_2() {
// Given:
final Opera nozzeDiFigaro = Composers.OperaFactory
.createOpera("Le Nozze di Figaro")
.language(Language.ITALIAN).librettist("Lorenzo Da Ponte")
.roles("Count Almaviva", "Countess Rosina", "Susanna", "Figaro")
.build();
Gramophone gramophone = new Gramophone();
// When:
gramophone.play(nozzeDiFigaro);
// Then:
await().atMost(5, TimeUnit.SECONDS).until(gramophone::isPlaying);
assertThat(gramophone.getCurrentOpera()).isEqualTo(nozzeDiFigaro);
}
18
Asynchronous Call
Polls until True or Timeout
@alexsotob
Deadlock Detection
Different Pollings
Fixed, Fibonacci, Iterative, Custom
Simple Library
No dependencies, No magic
Benefits of Awaitility
19
@alexsotob20
REST API
@alexsotob
GET /Ludwig+van+Beethoven
{
"name": "Ludwig van Beethoven",
"era": "ROMANTIC",
"birthdate": {},
"died": {},
"operas": [
{
"name": "Fidelio",
"librettist": "Georg Friedrich Treitschke",
"language": "GERMAN",
"roles": ["Rocco", "Leonore", "Florestan"]
}
]
}
21
Simple Objects
Array of Objects
@alexsotob
HttpClient Example
@Test
public void should_find_composer() throws IOException, URISyntaxException {
// Given:
URIBuilder uriBuilder = new URIBuilder("http://localhost:8080/");
uriBuilder.setPath("Ludwig van Beethoven");
// When:
final Content bodyContent = Request.Get(uriBuilder.build())
.execute().returnContent();
String body = bodyContent.asString();
// Then:
assertThat(body).contains(""name":"Ludwig van Beethoven"")
.contains(""librettist":"Georg Friedrich Treitschke"");
}
22
Prepare Connection
Do connection
Get content
Manipulate String
@alexsotob
WebDriver Example
// Given:
WebDriver browser = new FirefoxDriver();
URIBuilder uriBuilder = new URIBuilder("http://localhost:8080/");
uriBuilder.setPath("Ludwig van Beethoven");
// When:
browser.navigate().to(uriBuilder.build());
// Then:
assertThat(browser.getPageSource()).contains(""name":"Ludwig van Beethoven"");
23
@alexsotob24
@alexsotob
REST-assured Example
@Test
public void should_find_composer() {
given()
.when()
.get("{composer}", "Ludwig van Beethoven")
.then()
.assertThat()
.body("name", is("Ludwig van Beethoven"))
.body("operas.size()", is(1))
.body("operas.name", hasItems("Fidelio"));
}
25
GET Http Method with
Placeholders
GPath Expression
@alexsotob
REST-assured Request Specification
.get("http://example.com/{composer}", "Ludwig van Beethoven")
RequestSpecBuilder builder = new RequestSpecBuilder();
builder.setBaseUri("http://example.com");
given().spec(builder.build())...
26
Use domain directly
Use Spec Builder
Reuse Everywhere
@alexsotob
REST-assured Auth
given().auth().oauth2(accessToken).when()...
given().auth().form("John", "Doe", springSecurity().withCsrfFieldName("_csrf")).when()...
given().auth().basic("username", "password").when()...
27
@alexsotob
Custom Parsers
Not just JSON and XML
SSL Support
.relaxedHTTPSValidation()
Filters
Input/Output modification
JSON Schema Validation
Content not Important
More Features
of Rest-Assured
28
@alexsotob29
(Micro) Services Dependencies
@alexsotob
Network Down
Service Down
Limits on API
Component Not in Control
Micro-Services Dependencies Hell
Problems with Services
30
@alexsotob
Mock Http Component
Stub/Fake Http Server
Service Virtualization
Possible Solutions
31
@alexsotob32
Service Virtualization
@alexsotob
Service Virtualization Capture Mode
33
Service A External Network Service B
Scripts
Proxy
@alexsotob
Service Virtualization Simulate Mode
34
Service A External Network Service B
Scripts
Proxy
@alexsotob35
@alexsotob
Hoverfly Example
@ClassRule
public static HoverflyRule hoverflyRule =
HoverflyRule.inCaptureOrSimulationMode("getcomposers.json");
@Test
public void should_get_composers_from_composers_microservice() {
// Given:
ComposersGateway composersGateway = new ComposersGateway("operas.com", 8081);
// When:
Composer composer = composersGateway.getComposer("Ludwig van Beethoven");
// Then:
assertThat(composer.getName()).isEqualTo("Ludwig van Beethoven");
}
36
Start Hoverfly
Use Real Host
Get Data from Real
{
"data" : {
"pairs" : [{
"request" : {
"path" : "/Ludwig van Beethoven",
"method" : "GET",
"destination" : “operas.com:8081",
...
}
"response" : {
"status" : 200,
"body" : "{"name":"Ludwig van Beethoven",}",
"encodedBody" : false,
"headers" : {
"Connection" : [ "keep-alive" ],
...
}
}
}
}
Get Data from Proxy
@alexsotob37
Persistence Tests
@alexsotob
First attempt
@Test
public void should_find_composer_by_name() {
// Given:
clearDatabase(jdbcUri);
insertComposersData(jdbcUri);
ComposersRepository composersRepository = new ComposersRepository();
// When:
Composer mozart = composersRepository.findComposerByName("Wolfgang Amadeus Mozart");
// Then:
assertThat(mozart).returns("Wolfgang Amadeus Mozart", Composer::getName);
}
38
Prepare Database
Execute Query
@alexsotob39
APE
@alexsotob
APE SQL example
@Rule
public ArquillianPersistenceRule arquillianPersistenceRule =
new ArquillianPersistenceRule();
@DbUnit
@ArquillianResource
RdbmsPopulator rdbmsPopulator;
@Before
public void populateData() {
// Given:
rdbmsPopulator.forUri(jdbcUri).withDriver(Driver.class).withUsername("sa")
.withPassword("").usingDataSet("composers.yml")
.execute();
}
40
APE JUnit Rule
(not necessary with
Arquillian Runner)
Set DBUnit usage
Configure Connection and Dataset
Populate
composers:
- id: 1
name: Wolfgang Amadeus Mozart
birthdate: 27/1/1756
died: 5/12/1791
@alexsotob
APE SQL example
@After
public void clean_database() {
// Given:
rdbmsPopulator.forUri(jdbcUri).withDriver(Driver.class).withUsername("sa")
.withPassword("").usingDataSet("composers.yml")
.clean();
}
41
Clean After Test
Clean Database
@alexsotob
Boilerplate Code
Programmatic/Declarative
@UsingDataSet/@ShouldMatchDataSet
SQL Support
DBUnit and Flyway
REST API Support
Postman Collections
NoSQL Support
MongoDB, Couchbase, CouchDB, Vault, Redis, Infinispan
Benefits of Arquillian APE
42
@alexsotob43
Containers Are Burning
@alexsotob
Testing Containers
docker build -t myorg/myservice:1.0.0 .
docker run --rm -ti -p 8080:8080 myorg/myservice:1.0.0
docker-compose up
mvn clean test
docker-compose stop
44
Docker Run
Docker Compose Run
Run tests
Stop Docker Containers
@alexsotob45
CUBE
@alexsotob
Arquillian Cube Example
@RunWith(Arquillian.class)
public class HelloWorldTest {
@ArquillianResource
@DockerUrl(containerName = "helloworld", exposedPort = 8080)
RequestSpecBuilder requestSpecBuilder;
@Test
public void should_receive_ok_message() {
RestAssured
.given()
.spec(requestSpecBuilder.build())
.when()
.get()
.then()
.assertThat().body("status", equalTo("OK"));
}
}
46
Arquillian Runner
REST-Assured Integration
Environment Resolver
Normal REST-Assured Call
helloworld:
image: jonmorehouse/ping-pong
ports:
- "8080:8080"
src/test/docker/docker-compose.yml
@alexsotob
Arquillian Cube DSL
@RunWith(SpringRunner.class)
@SpringBootTest(classes = PingPongController.class, webEnvironment = RANDOM_PORT)
@ContextConfiguration(initializers = PingPongSpringBootTest.Initializer.class)
public class PingPongSpringBootTest {
@ClassRule
public static ContainerDslRule redis = new ContainerDslRule("redis:3.2.6")
.withPortBinding(6379);
@Autowired
TestRestTemplate restTemplate;
@Test
public void should_get_data_from_redis() {
}
47
Spring Boot Test
Custom Initializer
Container Definition
public static class Initializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
EnvironmentTestUtils.addEnvironment("testcontainers",
configurableApplicationContext.getEnvironment(),
"spring.redis.host=" + redis.getIpAddress(),
"spring.redis.port=" + redis.getBindPort(6379)
);
Sets Container Environment
@alexsotob
Arquillian Cube K8S
@RunWith(Arquillian.class)
public class HelloWorldTest {
@ArquillianResource
KubernetesClient client;
@Named(“hello-world-service")
@PortForward
@ArquillianResource
URL url;
@Test
public void testRunningPodStaysUp() throws Exception {
assertThat(client).deployments().pods().isPodReadyForPeriod();
}
}
48
Kubernetes Client
URL to Access Service
AssertJ Custom Assertions
@alexsotob49
Let’s Wind Down
@alexsotob
From Low to High Level
Unit, Component, Integration, Deployment
Not Just for Micro-Services
Same can be reused for monolithic
Improves Readability
Tests are meant to be read
Conclusions
50
@alexsotob51
Keep Calm
And Write Tests
Testing For Unicorns

More Related Content

What's hot

Riga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with JavassistRiga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with JavassistAnton Arhipov
 
20110424 action scriptを使わないflash勉強会
20110424 action scriptを使わないflash勉強会20110424 action scriptを使わないflash勉強会
20110424 action scriptを使わないflash勉強会Hiroki Mizuno
 
JPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream APIJPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream APItvaleev
 
Endevor api an introduction to the endevor application programming interface
Endevor api   an introduction to the endevor application programming interface Endevor api   an introduction to the endevor application programming interface
Endevor api an introduction to the endevor application programming interface Kevin Grimes
 
A comparison between C# and Java
A comparison between C# and JavaA comparison between C# and Java
A comparison between C# and JavaAli MasudianPour
 
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)jon_bell
 
TDOH x 台科 pwn課程
TDOH x 台科 pwn課程TDOH x 台科 pwn課程
TDOH x 台科 pwn課程Weber Tsai
 
Node.js API pitfalls
Node.js API pitfallsNode.js API pitfalls
Node.js API pitfallsTorontoNodeJS
 
The Ring programming language version 1.9 book - Part 103 of 210
The Ring programming language version 1.9 book - Part 103 of 210The Ring programming language version 1.9 book - Part 103 of 210
The Ring programming language version 1.9 book - Part 103 of 210Mahmoud Samir Fayed
 
Linux kernel debugging
Linux kernel debuggingLinux kernel debugging
Linux kernel debuggingJungMinSEO5
 
Institute management
Institute managementInstitute management
Institute managementvarun arora
 
Unbearable Test Code Smell
Unbearable Test Code SmellUnbearable Test Code Smell
Unbearable Test Code SmellSteven Mak
 
Network security mannual (2)
Network security mannual (2)Network security mannual (2)
Network security mannual (2)Vivek Kumar Sinha
 
G*におけるソフトウェアテスト・シーズンIII
G*におけるソフトウェアテスト・シーズンIIIG*におけるソフトウェアテスト・シーズンIII
G*におけるソフトウェアテスト・シーズンIIITakuma Watabiki
 
Самые вкусные баги из игрового кода: как ошибаются наши коллеги-программисты ...
Самые вкусные баги из игрового кода: как ошибаются наши коллеги-программисты ...Самые вкусные баги из игрового кода: как ошибаются наши коллеги-программисты ...
Самые вкусные баги из игрового кода: как ошибаются наши коллеги-программисты ...DevGAMM Conference
 

What's hot (20)

Riga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with JavassistRiga Dev Day 2016 - Having fun with Javassist
Riga Dev Day 2016 - Having fun with Javassist
 
20110424 action scriptを使わないflash勉強会
20110424 action scriptを使わないflash勉強会20110424 action scriptを使わないflash勉強会
20110424 action scriptを使わないflash勉強会
 
Elixir @ Paris.rb
Elixir @ Paris.rbElixir @ Paris.rb
Elixir @ Paris.rb
 
Object oriented JavaScript
Object oriented JavaScriptObject oriented JavaScript
Object oriented JavaScript
 
JPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream APIJPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream API
 
Endevor api an introduction to the endevor application programming interface
Endevor api   an introduction to the endevor application programming interface Endevor api   an introduction to the endevor application programming interface
Endevor api an introduction to the endevor application programming interface
 
A comparison between C# and Java
A comparison between C# and JavaA comparison between C# and Java
A comparison between C# and Java
 
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)
 
TDOH x 台科 pwn課程
TDOH x 台科 pwn課程TDOH x 台科 pwn課程
TDOH x 台科 pwn課程
 
TDD per Webapps
TDD per WebappsTDD per Webapps
TDD per Webapps
 
Node.js API pitfalls
Node.js API pitfallsNode.js API pitfalls
Node.js API pitfalls
 
The Ring programming language version 1.9 book - Part 103 of 210
The Ring programming language version 1.9 book - Part 103 of 210The Ring programming language version 1.9 book - Part 103 of 210
The Ring programming language version 1.9 book - Part 103 of 210
 
Linux kernel debugging
Linux kernel debuggingLinux kernel debugging
Linux kernel debugging
 
Institute management
Institute managementInstitute management
Institute management
 
Unbearable Test Code Smell
Unbearable Test Code SmellUnbearable Test Code Smell
Unbearable Test Code Smell
 
Network security mannual (2)
Network security mannual (2)Network security mannual (2)
Network security mannual (2)
 
Rust ⇋ JavaScript
Rust ⇋ JavaScriptRust ⇋ JavaScript
Rust ⇋ JavaScript
 
G*におけるソフトウェアテスト・シーズンIII
G*におけるソフトウェアテスト・シーズンIIIG*におけるソフトウェアテスト・シーズンIII
G*におけるソフトウェアテスト・シーズンIII
 
Introduction to asyncio
Introduction to asyncioIntroduction to asyncio
Introduction to asyncio
 
Самые вкусные баги из игрового кода: как ошибаются наши коллеги-программисты ...
Самые вкусные баги из игрового кода: как ошибаются наши коллеги-программисты ...Самые вкусные баги из игрового кода: как ошибаются наши коллеги-программисты ...
Самые вкусные баги из игрового кода: как ошибаются наши коллеги-программисты ...
 

Similar to Testing For Unicorns

Arquillian Constellation
Arquillian ConstellationArquillian Constellation
Arquillian ConstellationAlex Soto
 
Making Java more dynamic: runtime code generation for the JVM
Making Java more dynamic: runtime code generation for the JVMMaking Java more dynamic: runtime code generation for the JVM
Making Java more dynamic: runtime code generation for the JVMRafael Winterhalter
 
Deterministic simulation testing
Deterministic simulation testingDeterministic simulation testing
Deterministic simulation testingFoundationDB
 
Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)tarcieri
 
AST Transformations
AST TransformationsAST Transformations
AST TransformationsHamletDRC
 
Testing a 2D Platformer with Spock
Testing a 2D Platformer with SpockTesting a 2D Platformer with Spock
Testing a 2D Platformer with SpockAlexander Tarlinder
 
Expression trees in c#
Expression trees in c#Expression trees in c#
Expression trees in c#Oleksii Holub
 
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume LaforgeGroovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume LaforgeGuillaume Laforge
 
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 201910 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019Matt Raible
 
Voxxed Days Vilnius 2015 - Having fun with Javassist
Voxxed Days Vilnius 2015 - Having fun with JavassistVoxxed Days Vilnius 2015 - Having fun with Javassist
Voxxed Days Vilnius 2015 - Having fun with JavassistAnton Arhipov
 
Ast transformations
Ast transformationsAst transformations
Ast transformationsHamletDRC
 
Introduction aux Macros
Introduction aux MacrosIntroduction aux Macros
Introduction aux Macrosunivalence
 
Expression trees in c#, Алексей Голубь (Svitla Systems)
Expression trees in c#, Алексей Голубь (Svitla Systems)Expression trees in c#, Алексей Голубь (Svitla Systems)
Expression trees in c#, Алексей Голубь (Svitla Systems)Alina Vilk
 
G*ワークショップ in 仙台 Grails(とことん)入門
G*ワークショップ in 仙台 Grails(とことん)入門G*ワークショップ in 仙台 Grails(とことん)入門
G*ワークショップ in 仙台 Grails(とことん)入門Tsuyoshi Yamamoto
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and ProsperKen Kousen
 

Similar to Testing For Unicorns (20)

Arquillian Constellation
Arquillian ConstellationArquillian Constellation
Arquillian Constellation
 
Making Java more dynamic: runtime code generation for the JVM
Making Java more dynamic: runtime code generation for the JVMMaking Java more dynamic: runtime code generation for the JVM
Making Java more dynamic: runtime code generation for the JVM
 
Jasmine BDD for Javascript
Jasmine BDD for JavascriptJasmine BDD for Javascript
Jasmine BDD for Javascript
 
Deterministic simulation testing
Deterministic simulation testingDeterministic simulation testing
Deterministic simulation testing
 
Java VS Python
Java VS PythonJava VS Python
Java VS Python
 
Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)Concurrent programming with Celluloid (MWRC 2012)
Concurrent programming with Celluloid (MWRC 2012)
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
 
Testing a 2D Platformer with Spock
Testing a 2D Platformer with SpockTesting a 2D Platformer with Spock
Testing a 2D Platformer with Spock
 
Expression trees in c#
Expression trees in c#Expression trees in c#
Expression trees in c#
 
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume LaforgeGroovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
 
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 201910 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
 
GroovyConsole2
GroovyConsole2GroovyConsole2
GroovyConsole2
 
Solr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene EuroconSolr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene Eurocon
 
Voxxed Days Vilnius 2015 - Having fun with Javassist
Voxxed Days Vilnius 2015 - Having fun with JavassistVoxxed Days Vilnius 2015 - Having fun with Javassist
Voxxed Days Vilnius 2015 - Having fun with Javassist
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
Introduction aux Macros
Introduction aux MacrosIntroduction aux Macros
Introduction aux Macros
 
Expression trees in c#, Алексей Голубь (Svitla Systems)
Expression trees in c#, Алексей Голубь (Svitla Systems)Expression trees in c#, Алексей Голубь (Svitla Systems)
Expression trees in c#, Алексей Голубь (Svitla Systems)
 
G*ワークショップ in 仙台 Grails(とことん)入門
G*ワークショップ in 仙台 Grails(とことん)入門G*ワークショップ in 仙台 Grails(とことん)入門
G*ワークショップ in 仙台 Grails(とことん)入門
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and Prosper
 

More from Alex Soto

Kubernetes Native Java
Kubernetes Native JavaKubernetes Native Java
Kubernetes Native JavaAlex Soto
 
Reactive Programming for Real Use Cases
Reactive Programming for Real Use CasesReactive Programming for Real Use Cases
Reactive Programming for Real Use CasesAlex Soto
 
Chaos Engineering Kubernetes
Chaos Engineering KubernetesChaos Engineering Kubernetes
Chaos Engineering KubernetesAlex Soto
 
Chaos Engineering Kubernetes
Chaos Engineering KubernetesChaos Engineering Kubernetes
Chaos Engineering KubernetesAlex Soto
 
Microservices testing and automation
Microservices testing and automationMicroservices testing and automation
Microservices testing and automationAlex Soto
 
Testing in Production: From DevTestOops to DevTestOps
Testing in Production: From DevTestOops to DevTestOpsTesting in Production: From DevTestOops to DevTestOps
Testing in Production: From DevTestOops to DevTestOpsAlex Soto
 
Supersonic Subatomic Java
Supersonic Subatomic JavaSupersonic Subatomic Java
Supersonic Subatomic JavaAlex Soto
 
From DevTestOops to DevTestOps
From DevTestOops to DevTestOpsFrom DevTestOops to DevTestOps
From DevTestOops to DevTestOpsAlex Soto
 
Istio service mesh & pragmatic microservices architecture
Istio service mesh & pragmatic microservices architectureIstio service mesh & pragmatic microservices architecture
Istio service mesh & pragmatic microservices architectureAlex Soto
 
Zero Downtime Deployment in Microservices era
Zero Downtime Deployment in Microservices eraZero Downtime Deployment in Microservices era
Zero Downtime Deployment in Microservices eraAlex Soto
 
Service Mesh Patterns
Service Mesh PatternsService Mesh Patterns
Service Mesh PatternsAlex Soto
 
Supersonic, Subatomic Java
Supersonic, Subatomic JavaSupersonic, Subatomic Java
Supersonic, Subatomic JavaAlex Soto
 
Zero Downtime Deployment in Microservices era
Zero Downtime Deployment in Microservices eraZero Downtime Deployment in Microservices era
Zero Downtime Deployment in Microservices eraAlex Soto
 
Long Live and Prosper To Monolith
Long Live and Prosper To MonolithLong Live and Prosper To Monolith
Long Live and Prosper To MonolithAlex Soto
 
Sail in the cloud - An intro to Istio commit
Sail in the cloud - An intro to Istio commitSail in the cloud - An intro to Istio commit
Sail in the cloud - An intro to Istio commitAlex Soto
 
KubeBoot - Spring Boot deployment on Kubernetes
KubeBoot - Spring Boot deployment on KubernetesKubeBoot - Spring Boot deployment on Kubernetes
KubeBoot - Spring Boot deployment on KubernetesAlex Soto
 
Sail in the Cloud - An intro to Istio
Sail in the Cloud  - An intro to IstioSail in the Cloud  - An intro to Istio
Sail in the Cloud - An intro to IstioAlex Soto
 
Testing XXIst Century
Testing XXIst CenturyTesting XXIst Century
Testing XXIst CenturyAlex Soto
 
Live Long and Prosper to Monolith
Live Long and Prosper to MonolithLive Long and Prosper to Monolith
Live Long and Prosper to MonolithAlex Soto
 
Testing in the 21st Century (ExpoQA)
Testing in the 21st Century (ExpoQA)Testing in the 21st Century (ExpoQA)
Testing in the 21st Century (ExpoQA)Alex Soto
 

More from Alex Soto (20)

Kubernetes Native Java
Kubernetes Native JavaKubernetes Native Java
Kubernetes Native Java
 
Reactive Programming for Real Use Cases
Reactive Programming for Real Use CasesReactive Programming for Real Use Cases
Reactive Programming for Real Use Cases
 
Chaos Engineering Kubernetes
Chaos Engineering KubernetesChaos Engineering Kubernetes
Chaos Engineering Kubernetes
 
Chaos Engineering Kubernetes
Chaos Engineering KubernetesChaos Engineering Kubernetes
Chaos Engineering Kubernetes
 
Microservices testing and automation
Microservices testing and automationMicroservices testing and automation
Microservices testing and automation
 
Testing in Production: From DevTestOops to DevTestOps
Testing in Production: From DevTestOops to DevTestOpsTesting in Production: From DevTestOops to DevTestOps
Testing in Production: From DevTestOops to DevTestOps
 
Supersonic Subatomic Java
Supersonic Subatomic JavaSupersonic Subatomic Java
Supersonic Subatomic Java
 
From DevTestOops to DevTestOps
From DevTestOops to DevTestOpsFrom DevTestOops to DevTestOps
From DevTestOops to DevTestOps
 
Istio service mesh & pragmatic microservices architecture
Istio service mesh & pragmatic microservices architectureIstio service mesh & pragmatic microservices architecture
Istio service mesh & pragmatic microservices architecture
 
Zero Downtime Deployment in Microservices era
Zero Downtime Deployment in Microservices eraZero Downtime Deployment in Microservices era
Zero Downtime Deployment in Microservices era
 
Service Mesh Patterns
Service Mesh PatternsService Mesh Patterns
Service Mesh Patterns
 
Supersonic, Subatomic Java
Supersonic, Subatomic JavaSupersonic, Subatomic Java
Supersonic, Subatomic Java
 
Zero Downtime Deployment in Microservices era
Zero Downtime Deployment in Microservices eraZero Downtime Deployment in Microservices era
Zero Downtime Deployment in Microservices era
 
Long Live and Prosper To Monolith
Long Live and Prosper To MonolithLong Live and Prosper To Monolith
Long Live and Prosper To Monolith
 
Sail in the cloud - An intro to Istio commit
Sail in the cloud - An intro to Istio commitSail in the cloud - An intro to Istio commit
Sail in the cloud - An intro to Istio commit
 
KubeBoot - Spring Boot deployment on Kubernetes
KubeBoot - Spring Boot deployment on KubernetesKubeBoot - Spring Boot deployment on Kubernetes
KubeBoot - Spring Boot deployment on Kubernetes
 
Sail in the Cloud - An intro to Istio
Sail in the Cloud  - An intro to IstioSail in the Cloud  - An intro to Istio
Sail in the Cloud - An intro to Istio
 
Testing XXIst Century
Testing XXIst CenturyTesting XXIst Century
Testing XXIst Century
 
Live Long and Prosper to Monolith
Live Long and Prosper to MonolithLive Long and Prosper to Monolith
Live Long and Prosper to Monolith
 
Testing in the 21st Century (ExpoQA)
Testing in the 21st Century (ExpoQA)Testing in the 21st Century (ExpoQA)
Testing in the 21st Century (ExpoQA)
 

Recently uploaded

Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 

Recently uploaded (20)

Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 

Testing For Unicorns

  • 1. Testing For Unicorns From Unit to Deployment Tests Alex Soto
 @alexsotob
  • 2. @alexsotob2 Alex Soto Red Hat Engineer www.lordofthejars.com @alexsotob Who Am I?
  • 4. @alexsotob4 Click to add subtitle ASSERTIONS
  • 5. @alexsotob JUnit Test @Test public void should_find_composer_by_name() { // Given: Composers composers = new Composers(); // When: final Composer mozart = composers.findComposerByName("Wolfgang Amadeus Mozart"); // Then: assertEquals("Wolfgang Amadeus Mozart", mozart.getName()); assertEquals(Era.CLASSICAL, mozart.getEra()); assertEquals(LocalDate.of(1756, 1, 27), mozart.getBirthdate()); assertEquals(LocalDate.of(1791, 12, 5), mozart.getDied()); } 5 Readable name BDD style AssertEquals Order Depends On Equals
  • 7. @alexsotob AssertJ Test import static org.assertj.core.api.Assertions.assertThat; @Test public void should_find_composer_by_name() { // Given: Composers composers = new Composers(); // When: final Composer mozart = composers.findComposerByName("Wolfgang Amadeus Mozart”); // Then: assertThat(mozart.getName()).isEqualTo("Wolfgang Amadeus Mozart”); assertThat(mozart).returns("Wolfgang Amadeus Mozart", Composer::getName); assertThat(mozart.getBirthdate()).isEqualTo(LocalDate.of(1756, 1, 27)); assertThat(mozart).isEqualToComparingFieldByField(expectedMozart); assertThat(mozart).isEqualToIgnoringNullFields(expectedMozart); } 7 Static Import Readable Assertions Not Depending on Equals
  • 8. @alexsotob AssertJ Test Collections @Test public void should_find_operas_by_composer_name() { // Given: Composers composers = new Composers(); // When: final List<Opera> operas = composers.findOperasByComposerName("Wolfgang Amadeus Mozart"); // Then: assertThat(operas) .hasSize(2) .extracting(Opera::getName) .containsExactlyInAnyOrder("Die Zauberflöte", "Don Giovanni”); } 8 Train Call (IDE support) Create List with getName Result Methods for String
  • 9. @alexsotob AssertJ Soft Assertions @Test public void should_find_composer_by_name_soft_assertions() { // Given: Composers composers = new Composers(); // When: final Composer mozart = composers.findComposerByName("Wolfgang Amadeus Mozart"); // Then: SoftAssertions.assertSoftly(softly -> { softly.assertThat(mozart.getName()).isEqualTo("Wolfgang Amadeus Mozart"); softly.assertThat(mozart.getEra()).isEqualTo(Era.CLASSICAL); softly.assertThat(mozart.getBirthdate()).isEqualTo(LocalDate.of(1756, 1, 27)); softly.assertThat(mozart.getDied()).isEqualTo(LocalDate.of(1791, 12, 5)); }); } 9 Java 8 Lambda All assertions in Block
  • 11. @alexsotob Try/Catch @Test public void should_throw_exception_if_composer_not_found() { // Given: Composers composers = new Composers(); // When: try { final Composer salieri = composers.findComposerByName("Antonio Salieri"); fail(); } catch (IllegalArgumentException e) { // Then: assertEquals("Composer Antonio Salieri is not found", e.getMessage()); } } 11 Fails if Success
  • 12. @alexsotob JUnit @Test(expected = IllegalArgumentException.class) public void should_throw_exception_if_composer_not_found_version_2() { // Given: Composers composers = new Composers(); // When: final Composer salieri = composers.findComposerByName("Antonio Salieri"); } 12 Special Attribute
  • 13. @alexsotob AssertJ Exceptions @Test public void should_throw_exception_if_composer_not_found_version_3() { // Given: Composers composers = new Composers(); // When: Throwable thrown = catchThrowable(() -> composers.findComposerByName("Antonio Salieri")); // Then: assertThat(thrown).isInstanceOf(IllegalArgumentException.class) .withFailMessage("Composer Antonio Salieri is not found”); } 13 Catch Exception of Lambda Assertion Methods for Exceptions
  • 14. @alexsotob IDE Friendly Ctrl + Space works Assertions Generation ComposerAssert.assertThat(mozart).hasName(“Mozart”).hasBirthdate(LocalDate.of(..); Out-of-the-Box Assertions Guava, Joda, DB, Neo4j and Swing Benefits of AssertJ 14
  • 16. @alexsotob Asynchronous Call @Test public void should_play_operas() throws InterruptedException { // Given: final Opera nozzeDiFigaro = ...; Gramophone gramophone = new Gramophone(); // When: gramophone.play(nozzeDiFigaro); // Then: TimeUnit.SECONDS.sleep(3); assertThat(gramophone.getCurrentOpera()).isEqualTo(nozzeDiFigaro); } 16 Asynchronous Call Slowest Machine Time
  • 18. @alexsotob Awaitility Example @Test public void should_play_operas_version_2() { // Given: final Opera nozzeDiFigaro = Composers.OperaFactory .createOpera("Le Nozze di Figaro") .language(Language.ITALIAN).librettist("Lorenzo Da Ponte") .roles("Count Almaviva", "Countess Rosina", "Susanna", "Figaro") .build(); Gramophone gramophone = new Gramophone(); // When: gramophone.play(nozzeDiFigaro); // Then: await().atMost(5, TimeUnit.SECONDS).until(gramophone::isPlaying); assertThat(gramophone.getCurrentOpera()).isEqualTo(nozzeDiFigaro); } 18 Asynchronous Call Polls until True or Timeout
  • 19. @alexsotob Deadlock Detection Different Pollings Fixed, Fibonacci, Iterative, Custom Simple Library No dependencies, No magic Benefits of Awaitility 19
  • 21. @alexsotob GET /Ludwig+van+Beethoven { "name": "Ludwig van Beethoven", "era": "ROMANTIC", "birthdate": {}, "died": {}, "operas": [ { "name": "Fidelio", "librettist": "Georg Friedrich Treitschke", "language": "GERMAN", "roles": ["Rocco", "Leonore", "Florestan"] } ] } 21 Simple Objects Array of Objects
  • 22. @alexsotob HttpClient Example @Test public void should_find_composer() throws IOException, URISyntaxException { // Given: URIBuilder uriBuilder = new URIBuilder("http://localhost:8080/"); uriBuilder.setPath("Ludwig van Beethoven"); // When: final Content bodyContent = Request.Get(uriBuilder.build()) .execute().returnContent(); String body = bodyContent.asString(); // Then: assertThat(body).contains(""name":"Ludwig van Beethoven"") .contains(""librettist":"Georg Friedrich Treitschke""); } 22 Prepare Connection Do connection Get content Manipulate String
  • 23. @alexsotob WebDriver Example // Given: WebDriver browser = new FirefoxDriver(); URIBuilder uriBuilder = new URIBuilder("http://localhost:8080/"); uriBuilder.setPath("Ludwig van Beethoven"); // When: browser.navigate().to(uriBuilder.build()); // Then: assertThat(browser.getPageSource()).contains(""name":"Ludwig van Beethoven""); 23
  • 25. @alexsotob REST-assured Example @Test public void should_find_composer() { given() .when() .get("{composer}", "Ludwig van Beethoven") .then() .assertThat() .body("name", is("Ludwig van Beethoven")) .body("operas.size()", is(1)) .body("operas.name", hasItems("Fidelio")); } 25 GET Http Method with Placeholders GPath Expression
  • 26. @alexsotob REST-assured Request Specification .get("http://example.com/{composer}", "Ludwig van Beethoven") RequestSpecBuilder builder = new RequestSpecBuilder(); builder.setBaseUri("http://example.com"); given().spec(builder.build())... 26 Use domain directly Use Spec Builder Reuse Everywhere
  • 27. @alexsotob REST-assured Auth given().auth().oauth2(accessToken).when()... given().auth().form("John", "Doe", springSecurity().withCsrfFieldName("_csrf")).when()... given().auth().basic("username", "password").when()... 27
  • 28. @alexsotob Custom Parsers Not just JSON and XML SSL Support .relaxedHTTPSValidation() Filters Input/Output modification JSON Schema Validation Content not Important More Features of Rest-Assured 28
  • 30. @alexsotob Network Down Service Down Limits on API Component Not in Control Micro-Services Dependencies Hell Problems with Services 30
  • 31. @alexsotob Mock Http Component Stub/Fake Http Server Service Virtualization Possible Solutions 31
  • 33. @alexsotob Service Virtualization Capture Mode 33 Service A External Network Service B Scripts Proxy
  • 34. @alexsotob Service Virtualization Simulate Mode 34 Service A External Network Service B Scripts Proxy
  • 36. @alexsotob Hoverfly Example @ClassRule public static HoverflyRule hoverflyRule = HoverflyRule.inCaptureOrSimulationMode("getcomposers.json"); @Test public void should_get_composers_from_composers_microservice() { // Given: ComposersGateway composersGateway = new ComposersGateway("operas.com", 8081); // When: Composer composer = composersGateway.getComposer("Ludwig van Beethoven"); // Then: assertThat(composer.getName()).isEqualTo("Ludwig van Beethoven"); } 36 Start Hoverfly Use Real Host Get Data from Real { "data" : { "pairs" : [{ "request" : { "path" : "/Ludwig van Beethoven", "method" : "GET", "destination" : “operas.com:8081", ... } "response" : { "status" : 200, "body" : "{"name":"Ludwig van Beethoven",}", "encodedBody" : false, "headers" : { "Connection" : [ "keep-alive" ], ... } } } } Get Data from Proxy
  • 38. @alexsotob First attempt @Test public void should_find_composer_by_name() { // Given: clearDatabase(jdbcUri); insertComposersData(jdbcUri); ComposersRepository composersRepository = new ComposersRepository(); // When: Composer mozart = composersRepository.findComposerByName("Wolfgang Amadeus Mozart"); // Then: assertThat(mozart).returns("Wolfgang Amadeus Mozart", Composer::getName); } 38 Prepare Database Execute Query
  • 40. @alexsotob APE SQL example @Rule public ArquillianPersistenceRule arquillianPersistenceRule = new ArquillianPersistenceRule(); @DbUnit @ArquillianResource RdbmsPopulator rdbmsPopulator; @Before public void populateData() { // Given: rdbmsPopulator.forUri(jdbcUri).withDriver(Driver.class).withUsername("sa") .withPassword("").usingDataSet("composers.yml") .execute(); } 40 APE JUnit Rule (not necessary with Arquillian Runner) Set DBUnit usage Configure Connection and Dataset Populate composers: - id: 1 name: Wolfgang Amadeus Mozart birthdate: 27/1/1756 died: 5/12/1791
  • 41. @alexsotob APE SQL example @After public void clean_database() { // Given: rdbmsPopulator.forUri(jdbcUri).withDriver(Driver.class).withUsername("sa") .withPassword("").usingDataSet("composers.yml") .clean(); } 41 Clean After Test Clean Database
  • 42. @alexsotob Boilerplate Code Programmatic/Declarative @UsingDataSet/@ShouldMatchDataSet SQL Support DBUnit and Flyway REST API Support Postman Collections NoSQL Support MongoDB, Couchbase, CouchDB, Vault, Redis, Infinispan Benefits of Arquillian APE 42
  • 44. @alexsotob Testing Containers docker build -t myorg/myservice:1.0.0 . docker run --rm -ti -p 8080:8080 myorg/myservice:1.0.0 docker-compose up mvn clean test docker-compose stop 44 Docker Run Docker Compose Run Run tests Stop Docker Containers
  • 46. @alexsotob Arquillian Cube Example @RunWith(Arquillian.class) public class HelloWorldTest { @ArquillianResource @DockerUrl(containerName = "helloworld", exposedPort = 8080) RequestSpecBuilder requestSpecBuilder; @Test public void should_receive_ok_message() { RestAssured .given() .spec(requestSpecBuilder.build()) .when() .get() .then() .assertThat().body("status", equalTo("OK")); } } 46 Arquillian Runner REST-Assured Integration Environment Resolver Normal REST-Assured Call helloworld: image: jonmorehouse/ping-pong ports: - "8080:8080" src/test/docker/docker-compose.yml
  • 47. @alexsotob Arquillian Cube DSL @RunWith(SpringRunner.class) @SpringBootTest(classes = PingPongController.class, webEnvironment = RANDOM_PORT) @ContextConfiguration(initializers = PingPongSpringBootTest.Initializer.class) public class PingPongSpringBootTest { @ClassRule public static ContainerDslRule redis = new ContainerDslRule("redis:3.2.6") .withPortBinding(6379); @Autowired TestRestTemplate restTemplate; @Test public void should_get_data_from_redis() { } 47 Spring Boot Test Custom Initializer Container Definition public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext configurableApplicationContext) { EnvironmentTestUtils.addEnvironment("testcontainers", configurableApplicationContext.getEnvironment(), "spring.redis.host=" + redis.getIpAddress(), "spring.redis.port=" + redis.getBindPort(6379) ); Sets Container Environment
  • 48. @alexsotob Arquillian Cube K8S @RunWith(Arquillian.class) public class HelloWorldTest { @ArquillianResource KubernetesClient client; @Named(“hello-world-service") @PortForward @ArquillianResource URL url; @Test public void testRunningPodStaysUp() throws Exception { assertThat(client).deployments().pods().isPodReadyForPeriod(); } } 48 Kubernetes Client URL to Access Service AssertJ Custom Assertions
  • 50. @alexsotob From Low to High Level Unit, Component, Integration, Deployment Not Just for Micro-Services Same can be reused for monolithic Improves Readability Tests are meant to be read Conclusions 50