+ All Categories
Home > Software > 2014 Joker - Integration Testing from the Trenches

2014 Joker - Integration Testing from the Trenches

Date post: 20-Aug-2015
Category:
Upload: nicolas-frankel
View: 551 times
Download: 0 times
Share this document with a friend
Popular Tags:
78
Integration Testing from the Trenches Nicolas Fränkel October 2014
Transcript
Page 1: 2014 Joker - Integration Testing from the Trenches

Integration Testing from the Trenches

Nicolas Fränkel October 2014

Page 2: 2014 Joker - Integration Testing from the Trenches

2https://leanpub.com/integrationtest

Me, myself and I

Developer & Architect as consultant

Wide range of businesses & customers

Teacher & Trainer

Speaker

Blogger

http://blog.frankel.ch/

(http://morevaadin.com/)

Page 3: 2014 Joker - Integration Testing from the Trenches

3https://leanpub.com/integrationtest

Also an author

Page 4: 2014 Joker - Integration Testing from the Trenches

4https://leanpub.com/integrationtest

Plan

Integration Testing

What is that?

Challenges

Solution hints

Testing with resource dependencies

Database

Web Services

Testing In-container

Spring & Spring MVC

JavaEE

Page 5: 2014 Joker - Integration Testing from the Trenches

Basics

Page 6: 2014 Joker - Integration Testing from the Trenches

6https://leanpub.com/integrationtest

There are many different kinds of testing

Unit Testing

Mutation Testing

Integration Testing

GUI Testing

Performance Testing

Load Testing

Stress Testing

Endurance Testing

Security Testing

etc.

Page 7: 2014 Joker - Integration Testing from the Trenches

7https://leanpub.com/integrationtest

Unit Testing vs. Integration Testing

Unit Testing

Testing a unit (i.e. a class) in isolation

Integration Testing

Testing the collaboration of multiple units

"Sa

vate

fo

uet

té f

igur

e 1

" b

y D

an

iel -

Pho

to D

an

iel.

Page 8: 2014 Joker - Integration Testing from the Trenches

8https://leanpub.com/integrationtest

A concrete example

Let’s take an example

A prototype car

"20

11 N

issa

n L

eaf

WA

S 2

011

104

0"

by

Ma

rio

rdo

Ma

rio

Ro

be

rto

Du

ran

Ort

iz -

Ow

n w

ork

Page 9: 2014 Joker - Integration Testing from the Trenches

9https://leanpub.com/integrationtest

Unit Testing

Akin to testing each nut and bolt separately

Page 10: 2014 Joker - Integration Testing from the Trenches

10https://leanpub.com/integrationtest

Integration Testing

Akin to going on a test drive

"UR

E0

5e

" b

y M

arv

in R

aaijm

ake

rs -

Ow

n w

ork

.

Page 11: 2014 Joker - Integration Testing from the Trenches

11https://leanpub.com/integrationtest

Unit Testing + Integration Testing

Approaches are not exclusive but complementary

Would you take a prototype car on test drive without having tested only nuts and bolts?

Would you manufacture a car from a prototype having only tested nuts and bolts but without having tested it on numerous test drives?

Page 12: 2014 Joker - Integration Testing from the Trenches

12https://leanpub.com/integrationtest

System Under Test

The SUT is what get tested

Techniques from Unit Testing can be re-used

Dependency Injection

Test doubles

Page 13: 2014 Joker - Integration Testing from the Trenches

13https://leanpub.com/integrationtest

Testing is about ROI

The larger the SUT

The more fragile the test

The less maintainable the test

The less the ROI

Thus, tests have to be organized in a pyramidal way

The bigger the SUT

The less the number of tests

Integration Testing

Test standard cases

Generally not error cases htt

p://

mar

tinfo

wle

r.co

m/b

liki/T

est

Pyr

am

id.h

tml

Page 14: 2014 Joker - Integration Testing from the Trenches

14https://leanpub.com/integrationtest

Integration Testing Challenges

Brittle

Dependent on external resources Database(s) etc.

Slow

Dependent on external resources

Hard to diagnose

Page 15: 2014 Joker - Integration Testing from the Trenches

15https://leanpub.com/integrationtest

How to cope

Separate Integration Tests from Unit Tests

Fake required infrastructure resources

Test in-container

Page 16: 2014 Joker - Integration Testing from the Trenches

16https://leanpub.com/integrationtest

But IT are still slow?!

Separating UT & IT doesn’t make IT run faster

But you can uncover errors from UT faster

Fail Fast

It will speed testing

"Ge

pard

jagt

2 (

Aci

no

nyx

jub

atu

s)"

by

Ma

len

e T

hys

sen

- O

wn

wo

rk.

Page 17: 2014 Joker - Integration Testing from the Trenches

17https://leanpub.com/integrationtest

Integration Testing and build

Available tools

Ant

Maven

Gradle

etc.

New

Dev

elo

pm

en

t Re

cen

tly F

inis

he

d o

n B

rist

ol's

City

Ce

ntr

e b

y B

rizz

leb

oy

Page 18: 2014 Joker - Integration Testing from the Trenches

18https://leanpub.com/integrationtest

Maven lifecycle

compile

test

pre-integration-test

integration-test

post-integration-test

verify

Page 19: 2014 Joker - Integration Testing from the Trenches

19https://leanpub.com/integrationtest

Reminder on Surefire

Bound to the test phase

Runs by default

*Test

Test*

*TestCase

Page 20: 2014 Joker - Integration Testing from the Trenches

20https://leanpub.com/integrationtest

Failsafe

“Copy” of Surefire

Different defaults

*IT

IT*

*ITCase

One goal per lifecycle phase

pre-integration-test

integration-test

post-integration-test

verify

Must be bound explicitly

Page 21: 2014 Joker - Integration Testing from the Trenches

21https://leanpub.com/integrationtest

Binding Failsafe - sample

<plugin> <artifactId>maven-failsafe-plugin</artifactId> <version>2.17</version> <executions> <execution> <id>integration-test</id> <goals> <goal>integration-test</goal> </goals> <phase>integration-test</phase> </execution> <execution> <id>verify</id> <goals> <goal>verify</goal> </goals> <phase>verify</phase> </execution> </executions></plugin>

Page 22: 2014 Joker - Integration Testing from the Trenches

22https://leanpub.com/integrationtest

Continuous Integration

Needs a build configured

Suggestions

Unit Tests run at each commit

Integration Tests run “regularly” Daily Hourly Depending on the context

Page 23: 2014 Joker - Integration Testing from the Trenches

Infrastructure dependencies

Page 24: 2014 Joker - Integration Testing from the Trenches

24https://leanpub.com/integrationtest

Infrastructure dependencies

Database

Filesystem

Time

Message Oriented Middleware

Mail server

FTP server

etc.

Page 25: 2014 Joker - Integration Testing from the Trenches

25https://leanpub.com/integrationtest

Mocks and infrastructure dependencies

To test your Service

Mock your DAO/repository Mockito

To test your DAO/repository

Mock your database???

Page 26: 2014 Joker - Integration Testing from the Trenches

26https://leanpub.com/integrationtest

Simple database use-case

Oracle database

Use an in-memory datasource and hope for the best

Use Oracle Express and hope for the best

Use a dedicated remote schema for each developer And your DBAs will hate you

Page 27: 2014 Joker - Integration Testing from the Trenches

27https://leanpub.com/integrationtest

Reducing database gap risk

In-memory databases are easy to setup

h2 is such a database

(successor of HSQL)

Compatibility modes for most widespread DB jdbc:h2:mem:test;MODE=Oracle

Page 28: 2014 Joker - Integration Testing from the Trenches

28https://leanpub.com/integrationtest

Parameterizing properties

Use properties for tests only

db.url=

db.driver=

db.username=

db.password=

And use your favorite build tool

Maven Resource filtering

Ant

Gradle

Page 29: 2014 Joker - Integration Testing from the Trenches

29https://leanpub.com/integrationtest

Integration Testing with Web Services

Web Services also are an infrastructure resource

Hosted on-site

Or outside

Different Web Services types have different solutions

RESTful

SOAP

Page 30: 2014 Joker - Integration Testing from the Trenches

30https://leanpub.com/integrationtest

Faking RESTful WS

Require an HTTP server

Requirements

Easy setup

Standalone

Embeddable in tests

Spring MVC?

Requires a servlet container (Not with Spring Boot)

Some code to write

Aut

ho

r: D

wig

ht S

iple

r fr

om

Sto

w,

MA

, U

SA

Page 31: 2014 Joker - Integration Testing from the Trenches

31https://leanpub.com/integrationtest

Spark to the rescue

Micro web framework

A la Sinatra

http://www.sparkjava.com/

Very few lines of code

Just wire to serve JSON files

Page 32: 2014 Joker - Integration Testing from the Trenches

32https://leanpub.com/integrationtest

Spark sample

import static spark.Spark.*;import spark.*;

public class SparkSample{ public static void main(String[] args) { setPort(5678); get("/hello", (request, response) -> { return "Hello World!"; }); get("/users/:name", (request, response) -> { return "User: " + request.params(":name"); }); get("/private", (request, response) -> { response.status(401); return "Go Away!!!"; }); }}

Page 33: 2014 Joker - Integration Testing from the Trenches

33https://leanpub.com/integrationtest

Faking SOAP web service

Possible to use Spark for SOAP

But unwieldy

Page 34: 2014 Joker - Integration Testing from the Trenches

34https://leanpub.com/integrationtest

SOAPUI

SOAPUI is the framework to test SOAP WS

Has a GUI

Good documentation

Understands Authentication Headers Etc.

Can be used to Fake SOAP WS

Page 35: 2014 Joker - Integration Testing from the Trenches

35https://leanpub.com/integrationtest

SOAPUI usage

Get WSDL

Either online

Or from a file

Create MockService

Craft the adequate response

Run the service

Point the dependency to localhost

Page 36: 2014 Joker - Integration Testing from the Trenches

37https://leanpub.com/integrationtest

Challenges to the previous scenario

Craft the adequate response?

More likely get one from the real WS

And tweak it

Running in an automated way

Save the project

Get the SOAPUI jar

Read the project and launch

Page 37: 2014 Joker - Integration Testing from the Trenches

38https://leanpub.com/integrationtest

SOAPUI automation

WsdlProject project = new WsdlProject();String wsdlFile = "file:src/test/resources/ip2geo.wsdl";WsdlInterface wsdlInterface = importWsdl(project, wsdlFile, true)[0];WsdlMockService fakeService = project.addNewMockService("fakeService");WsdlOperation wsdlOp = wsdlInterface.getOperationByName("ResolveIP");MockOperation fakeOp = fakeService.addNewMockOperation(wsdlOp);MockResponse fakeResponse = fakeOp.addNewMockResponse("fakeResponse");fakeResponse.setResponseContent( "<soapenv:Envelope ...</soapenv:Envelope>");runner = fakeService.start();

Page 38: 2014 Joker - Integration Testing from the Trenches

39https://leanpub.com/integrationtest

Faking Web Service in real-life

Use the same rules as for UT

Keep validation simple

Test one thing One Assert Or a set of related ones

Keep setup simple

Don’t put complex logic Don’t put too much logic Don’t put logic at all

Duplicate setup in each test Up to a point

Aut

ho

r: I

, ro

lf B

Page 39: 2014 Joker - Integration Testing from the Trenches

In-container Testing

Page 40: 2014 Joker - Integration Testing from the Trenches

41https://leanpub.com/integrationtest

Upping the ante

Testing collaboration is nice

Faking infrastructure dependencies is nice

But didn’t we forget the most important dependency?

Page 41: 2014 Joker - Integration Testing from the Trenches

42https://leanpub.com/integrationtest

The container!

“Proprietary” container

Spring

Application Server

Tomcat

JBoss

<Place your favorite one here>

Page 42: 2014 Joker - Integration Testing from the Trenches

43https://leanpub.com/integrationtest

Spring

So far, we can test:

Beans which dependencies can be mocked (or not) Service

Beans that depend on fake resources Datasource

What about the configuration?

In Unit Tests, we set dependencies The real configuration is not used Ergo, not tested!

Page 43: 2014 Joker - Integration Testing from the Trenches

44https://leanpub.com/integrationtest

Testing configuration

Configuration cannot be monolithic

Break down into fragments

Each fragment contains a set of either Real beans Fake beans

Rud

sto

n M

on

olith

Ma

y 2

013

by

An

ge

la F

ind

lay

Page 44: 2014 Joker - Integration Testing from the Trenches

45https://leanpub.com/integrationtest

Data source configuration fragment management example

Different configuration fragments

Production JNDI fragment

Test in-memory fragment

Page 45: 2014 Joker - Integration Testing from the Trenches

46https://leanpub.com/integrationtest

Data source configuration sample

<beans ...> <jee:jndi-lookup id="ds" jndi-name="jdbc/MyDS" /></beans>

<beans ...> <bean id="ds" class="o.a.t.jdbc.pool.DataSource"> <property name="driverClassName” value="org.h2.Driver" /> <property name="url" value="jdbc:h2:~/test" /> <property name="username" value="sa" /> <property name="maxActive" value="1" /> </bean></beans>

Page 46: 2014 Joker - Integration Testing from the Trenches

47https://leanpub.com/integrationtest

Fragment structure

1. Main fragment

Repository

Service

etc.

2. Prod DB fragment

3. Test DB fragment

Page 47: 2014 Joker - Integration Testing from the Trenches

48https://leanpub.com/integrationtest

Tips

Prevent coupling

No fragments reference in fragments

Use top-level assembly instead Tests Application Context Webapps

Pool exhaustion check

Set the maximum number of connections in the pool to 1

Compile-time safety

Use JavaConfig

Not related to testing

Page 48: 2014 Joker - Integration Testing from the Trenches

49https://leanpub.com/integrationtest

And now, how to test?

Get access to both

The entry point

And the “end” point

Spring Test to the rescue

Integration with common Testing frameworks JUnit TestNG

St L

ou

is G

ate

wa

y A

rch

19

16"

by

Dirk

Be

yer

- O

wn

wo

rk.

Page 49: 2014 Joker - Integration Testing from the Trenches

50https://leanpub.com/integrationtest

Favor TestNG

Extra grouping

Per layer

Per use-case

Name your own

Extra lifecycle hooks

Better parameterization

Data Provider

Ordering of test methods

Page 50: 2014 Joker - Integration Testing from the Trenches

51https://leanpub.com/integrationtest

Spring TestNG integration

AbstractTestNGSpringContextTests

AbstractTransactionalTestNGSpringContextTests

Configurable context fragments

@ContextConfiguration

Inject any bean in the test class

If necessary, applicatonContext member from superclass

Page 51: 2014 Joker - Integration Testing from the Trenches

52https://leanpub.com/integrationtest

Sample TestNG test with Spring

@ContextConfiguration( classes = { MainCfg.class, AnotherCfg.class })public class OrderIT extends AbstractTestNGSpringContextTests {

@Autowired private OrderService orderService;

@Test public void should_do_this_and_that() { orderService.order(); Assert.assertThat(...) }}

Page 52: 2014 Joker - Integration Testing from the Trenches

53https://leanpub.com/integrationtest

Testing with the DB (or other transactional resources)

Transactions

Bound to business functionality

Implemented on Service layer

With DAO

Use explicit transaction management

@Transactional

Page 53: 2014 Joker - Integration Testing from the Trenches

54https://leanpub.com/integrationtest

Transaction management tip

Tests fail… sometimes

How to audit state?

By default, Spring rollbacks transactions

General configuration

@TransactionConfiguration( defaultRollback = false)

Can be overridden on a per-method basis @Rollback(true)

Page 54: 2014 Joker - Integration Testing from the Trenches

55https://leanpub.com/integrationtest

Sample Transaction management

@ContextConfiguration@TransactionConfiguration(defaultRollback = false)public class OverrideDefaultRollbackSpringTest extends AbstractTransactionalTestNGSpringContextTests {

@Test @Rollback(true) public void transaction_will_be_rollbacked() { ... }

@Test public void transaction_wont_be_rollbacked() { ... }}

Page 55: 2014 Joker - Integration Testing from the Trenches

56https://leanpub.com/integrationtest

Spring MVC webapps Testing

Require a context hierachy

Parent as main context

Child as webapp context

@ContextHierarchy

Require a webapp configuration

@WebAppConfiguration

Page 56: 2014 Joker - Integration Testing from the Trenches

57https://leanpub.com/integrationtest

Spring MVC test sample

@WebAppConfiguration@ContextHierarchy({ @ContextConfiguration(classes = MainConfig.class), @ContextConfiguration(classes = WebConfig.class)})public class SpringWebApplicationTest extends AbstractTestNGSpringContextTests { ...}

Page 57: 2014 Joker - Integration Testing from the Trenches

58https://leanpub.com/integrationtest

Entry points for testing Spring webapps

At the HTML level

At the HTTP level

At the Controller level

Like standard Java testing

"La

hn

tun

ne

l Wei

lbu

rg"

by

rup

p.d

e -

Ow

n w

ork

.

Page 58: 2014 Joker - Integration Testing from the Trenches

59https://leanpub.com/integrationtest

Tools for testing webapps

HTML testing tools

Interact with HTML/CSS Fill this field Click on that button

HTTP testing tools Send HTTP requests Get HTTP responses

Page 59: 2014 Joker - Integration Testing from the Trenches

60https://leanpub.com/integrationtest

Drawback of previous approaches

Very low-level

Fragile!

Remember that testing is about ROI Breaking tests with every

HTML/CSS change is the worst way to have positive ROI

(There are mitigation techniques out of scope)

Attr

ibu

tion:

© M

ilan

Nyk

od

ym,

Cze

ch R

ep

ubl

ic

Page 60: 2014 Joker - Integration Testing from the Trenches

61https://leanpub.com/integrationtest

Drawback of Testing with controllers as entry point

Bypass many URL-related features

Interceptors

Spring Security

etc.

Con

tro

ller

SC

SI.

JPG

by

Ro

sco

Page 61: 2014 Joker - Integration Testing from the Trenches

62https://leanpub.com/integrationtest

Spring Test to the rescue

Spring Test has a large chunk dedicated to MVC

Since 3.2

Can test with URL as entry-points

Fluent API with static imports

Coa

stg

uar

d H

elic

op

ter

(80

160

50

677

)" b

y P

au

l Luc

as

fro

m L

eic

est

ersh

ire

, UK

- C

oas

tgu

ard

He

lico

pte

r

Page 62: 2014 Joker - Integration Testing from the Trenches

63https://leanpub.com/integrationtest

Spring MVC Test overview

Page 63: 2014 Joker - Integration Testing from the Trenches

64https://leanpub.com/integrationtest

MockMvc class responsibilities

Request builder

Configures the Fake request

Request matcher

Misc. assertions

Request handler

Do something OOB logger

Page 64: 2014 Joker - Integration Testing from the Trenches

65https://leanpub.com/integrationtest

Available configuration on Request Builder

HTTP method

GET

POST

etc.

HTTP related stuff

Headers

Parameters

Content

JavaEE related stuff

Request attributes

Session

etc.

Page 65: 2014 Joker - Integration Testing from the Trenches

66https://leanpub.com/integrationtest

Request Builder sample

MockHttpServletRequestBuilder builder =get("/customer/{id}", 1234L).accept("text/html").param("lang", "en").secure(true);

GET /customer/1234?lang=en HTTP/1.1 Accept: text/html

Page 66: 2014 Joker - Integration Testing from the Trenches

67https://leanpub.com/integrationtest

You can use constants in your @RequestMapping

@Controllerpublic class MyController {

public static final String PATH = "/customer/{id}";

@RequestMapping(PATH)public String showCustomer() { ... }

}

MockHttpServletRequestBuilder builder = get(PATH, 1L);

Page 67: 2014 Joker - Integration Testing from the Trenches

68https://leanpub.com/integrationtest

Some matchers

Checks result is a

Forward Either exact Or regexp

Redirect Either exact Or regexp

JSON payload

a s

afe

ty w

ax

ma

tch

bo

x a

nd

ma

tch

es

by

Aa

thav

an

jaffn

a

Page 68: 2014 Joker - Integration Testing from the Trenches

69https://leanpub.com/integrationtest

Some other matchers

Request class

Handler class

Controller

Content class

Cookie class

Status class

HTTP code

Flash class

(Attributes, not the techno)

View class

Model class "Ove

jas

en

Pa

tag

onia

- A

rge

ntin

a"

by

wri

tte

carl

osa

nto

nio

Page 69: 2014 Joker - Integration Testing from the Trenches

70https://leanpub.com/integrationtest

Spring Pet Clinic

Page 70: 2014 Joker - Integration Testing from the Trenches

71https://leanpub.com/integrationtest

Integration Testing on Spring Pet Clinic

@WebAppConfiguration@ContextHierarchy({ @ContextConfiguration("classpath:spring/business-config.xml"), @ContextConfiguration("classpath:spring/mvc-core-config.xml")})@ActiveProfiles("jdbc")public class PetControlIT extends AbstractTestNGSpringContextTests {

@Test public void should_display_create_form() throws Exception { WebApplicationContext wac = (WebApplicationContext) applicationContext; MockMvc mvc = MockMvcBuilders.webAppContextSetup(wac).build(); MockHttpServletRequestBuilder newPet =

get("/owners/{ownerId}/pets/new", 1); mvc.perform(newPet) .andExpect(view().name("pets/createOrUpdatePetForm")) .andExpect(model().attributeExists("pet")); }}

Page 71: 2014 Joker - Integration Testing from the Trenches

72https://leanpub.com/integrationtest

The JavaEE world

JavaEE has unique challenges

CDI has no explicit wiring You can @Veto you own

classes But no compiled ones

Different application servers Same specifications Different implementations

Page 72: 2014 Joker - Integration Testing from the Trenches

73https://leanpub.com/integrationtest

Deploy only what you want

Standalone API to deploy only resources relevant to the test

Just pick and choose

Maven Integration

Gradle too…

Page 73: 2014 Joker - Integration Testing from the Trenches

74https://leanpub.com/integrationtest

Shrinkwrap sample

String srcMainWebapp = "src/main/webapp/";ShrinkWrap.create(WebArchive.class, "myWar.war") .addClass(MyService.class) .addPackage(MyModel.class.getPackage()) .addAsWebInfResource("persistence.xml", "classes/META-INF/persistence.xml") .addAsWebInfResource( new File(srcMainWebapp, "WEB-INF/page/my.jsp"), "page/my.jsp") .addAsWebResource( new File(srcMainWebapp, "script/my.js"), "script/my.js") .setWebXML("web.xml");

Page 74: 2014 Joker - Integration Testing from the Trenches

75https://leanpub.com/integrationtest

Maven integration sample

File[] libs = Maven.resolver() .loadPomFromFile("pom.xml") .importDependencies(COMPILE,

RUNTIME).resolve() .withTransitivity().asFile();

ShrinkWrap.create(WebArchive.class, "myWar.war") .addAsLibraries(libs);

Page 75: 2014 Joker - Integration Testing from the Trenches

76https://leanpub.com/integrationtest

Different application servers

Abstraction layer to

Download

Deploy applications

Test

Container adapters

TomEE

JBoss

Weld

etc.

Full Maven integration

Page 76: 2014 Joker - Integration Testing from the Trenches

77https://leanpub.com/integrationtest

Arquillian Test sample

public class ArquillianSampleIT extends Arquillian {

@Inject private MyService myService;

@Deployment public static JavaArchive createDeployment() { return ...; }

@Test public void should_handle_service() { Object value = myService.handle(); Assert.assertThat(...); }}

Page 77: 2014 Joker - Integration Testing from the Trenches

78https://leanpub.com/integrationtest

Arquillian configuration sample

<arquillian xmlns="http://jboss.org/schema/arquillian" xmlns:xsi="..." xsi:schemaLocation=" http://jboss.org/schema/arquillianhttp://jboss.org/schema/arquillian/arquillian_1_0.xsd"> <container qualifier="tomee" default="true"> <configuration> <property name="httpPort">-1</property> <property name="stopPort">-1</property> </configuration></arquillian>

Page 78: 2014 Joker - Integration Testing from the Trenches

https://leanpub.com/integrationtest

Twitter: @itfromtrenches


Recommended