Java Day Kharkiv - Integration Testing from the Trenches Rebooted

Post on 17-Jan-2017

204 views 3 download

transcript

INTEGRATION TESTING FROM THE TRENCHESREBOOTED@NICOLAS_FRANKEL

https://leanpub.com/integrationtest/ 2

ME, MYSELF AND I

https://leanpub.com/integrationtest/ 3

FROM THE BOOK

4https://leanpub.com/integrationtest/

INTRODUCTION

INTEGRATION TESTING FROM THE TRENCHES - REBOOTED

https://leanpub.com/integrationtest/ 5

TESTING?Unit TestingMutation TestingGUI TestingPerformance Testing• Load Testing• Stress Testing• Endurance Testing

Security Testingetc.

https://leanpub.com/integrationtest/ 6

UNIT VS. INTEGRATION TESTINGUnit Testing• Testing a unit in isolation

Integration Testing• Testing the collaboration of

multiple units

https://leanpub.com/integrationtest/ 7

EXAMPLEA prototype car

https://leanpub.com/integrationtest/ 8

UNIT TESTINGAkin to testing each nut and bolt separately

https://leanpub.com/integrationtest/ 9

INTEGRATION TESTINGAkin to going on a test drive

https://leanpub.com/integrationtest/ 10

UNIT + INTEGRATION TESTINGTake a prototype car on a test drive having tested only nuts and bolts?Manufacture a car having tested nuts and bolts but without having tested it on numerous test drives?

https://leanpub.com/integrationtest/ 11

SYSTEM UNDER TESTSUT is what get testedTechniques from Unit Testing can be re-used•Dependency Injection• Test doubles

https://leanpub.com/integrationtest/ 12

REMINDER: TEST DOUBLESDummyMockStubSpyFake

https://leanpub.com/integrationtest/ 13

TESTING IS ABOUT ROIThe larger the SUT• The more fragile the test• The less maintainable the

test• The less the ROI

https://leanpub.com/integrationtest/ 14

TESTING IS ABOUT ROITests have to be organized in a certain way• The bigger the SUT• The less the number of

tests

https://leanpub.com/integrationtest/ 15

TESTING IS ABOUT ROIIntegration Testing• Test nominal cases

16https://leanpub.com/integrationtest/

INTEGRATION TESTING CHALLENGES

INTEGRATION TESTING FROM THE TRENCHES - REBOOTED

https://leanpub.com/integrationtest/ 17

INTEGRATION TESTS CHALLENGESSlowFragileHard to diagnose

https://leanpub.com/integrationtest/ 18

Y U SLOW?Use infrastructure resourcesUse container

https://leanpub.com/integrationtest/ 19

COPING WITH SLOWNESSSeparate Integration Tests from Unit Tests

https://leanpub.com/integrationtest/ 20

INTEGRATION TESTS ARE STILL SLOWSeparating IT doesn’t make them fasterBut errors can be uncovered faster• Fail fast• It will speed testing

https://leanpub.com/integrationtest/ 21

HOW TO SEPARATE?Depends on the build tool•Ant•Maven•Gradle• Something else?

https://leanpub.com/integrationtest/ 22

REMINDER: MAVEN LIFECYCLE

compiletest package

integration-test

pre-integration-test

verifypost-in

tegration-test

compiler:compile

surefire:test

https://leanpub.com/integrationtest/ 23

MAVEN SUREFIRE PLUGINBound to the test phaseRuns by default•*Test•Test*•*TestCase

https://leanpub.com/integrationtest/ 24

MAVEN FAILSAFE PLUGIN“Copy” of SurefireDifferent defaults•*IT•IT*•*ITCase

https://leanpub.com/integrationtest/ 25

MAVEN FAILSAFE PLUGINOne goal per lifecycle phase• pre-integration-test• integration-test• post-integration-test• verify

Must be bound explicitly

https://leanpub.com/integrationtest/ 26

POM SNIPPET<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>

https://leanpub.com/integrationtest/ 27

CONTINUOUS INTEGRATIONUnit Tests run at each commitIntegration Tests run “regularly”• Daily• Hourly• Depending on the context

https://leanpub.com/integrationtest/ 28

Y U FRAGILE?Usage of infrastructure resources• External•Multiple

https://leanpub.com/integrationtest/ 29

INFRASTRUCTURE RESOURCESFile systemTimeDatabasesWeb ServicesMail serversFTP Serversetc.

https://leanpub.com/integrationtest/ 30

TIME/FILE SYSTEM:COPING WITH FRAGILITY

Use Dependency InjectionUse abstractions• e.g. java.nio.file.Path instead of java.util.File

https://leanpub.com/integrationtest/ 31

DATABASES:COPING WITH FRAGILITY

Test the Service layer•Mock the repository

Test the Repository layer•Mock the database???

https://leanpub.com/integrationtest/ 32

DATABASES:COPING WITH FRAGILITY

Use Fakes under your control

https://leanpub.com/integrationtest/ 33

ORACLE DATABASE USE-CASEUse an in-memory data source and hope for the bestUse Oracle Express and hope for the bestUse a dedicated remote schema for each developer• And your DBAs will hate you

https://leanpub.com/integrationtest/ 34

TRADE-OFFThe closer to the “real” infrastructure,the more complex the setup

https://leanpub.com/integrationtest/ 35

MANAGING THE GAP RISKIn-memory databases are easy to setuph2 is such a database• Compatibility modes for

most widespread DB• jdbc:h2:mem:test;MODE=Oracle

https://leanpub.com/integrationtest/ 36

WEB SERVICES:COPING WITH FRAGILITY

Web Services as infrastructure resources• Hosted on-site• Or outside

Different architectures• REST(ful)• SOAP

https://leanpub.com/integrationtest/ 37

WEB SERVICES:COPING WITH FRAGILITY

Use Fakes under your control

https://leanpub.com/integrationtest/ 38

FAKE RESTFUL WEB SERVICESSpark•Micro web framework•A la Sinatra•Very few lines of code• Just serve static JSON files

https://leanpub.com/integrationtest/ 39

SPARK SAMPLEimport 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!!!"; }); }}

https://leanpub.com/integrationtest/ 40

FAKE SOAP WEB SERVICESPossible with Spark• But not efficient• Remember about ROI

https://leanpub.com/integrationtest/ 41

SMARTBEAR SOAPUI

https://leanpub.com/integrationtest/ 42

SMARTBEAR SOAPUIHas a GUIGood documentationUnderstands•Authentication•Headers• Etc.

https://leanpub.com/integrationtest/ 43

SOAPUI USAGEGet WSDL• Either online• Or from a file

Create MockService• Craft the adequate response

Run the servicePoint the dependency to localhost

CHALLENGES TO THE PREVIOUS SCENARIOCraft 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

https://leanpub.com/integrationtest/ 45

SOAPUI APIWsdlProject 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();

https://leanpub.com/integrationtest/ 46

FAKING WEB SERVICE IN REAL-LIFEUse the same rules as for UT• Keep validation simple• Test one thing

Keep setup simple• Don’t put complex logic• OK to duplicate setup in each test

• Up to a point

Auth

or: I

, rol

f B

47https://leanpub.com/integrationtest/

IN-CONTAINER TESTING

INTEGRATION TESTING FROM THE TRENCHES - REBOOTED

https://leanpub.com/integrationtest/ 48

INTEGRATION TESTINGCollaboration between classesBoundaries with external dependenciesWhat did we forget?

https://leanpub.com/integrationtest/ 49

DEPENDENCIESThe most important dependency is the container!• Spring• Java EE•Application server

https://leanpub.com/integrationtest/ 50

SPRING CONFIGURATION TESTINGSo far, we can test:• Beans whose dependencies

can be mocked• Beans that depend on fake

resourcesWhat about the configuration?

https://leanpub.com/integrationtest/ 51

DESIGNING TESTABLE CONFIGURATIONConfiguration cannot be monolithic• Break down into fragments• Each fragment contains a set

of either• Real beans• Fake beans

https://leanpub.com/integrationtest/ 52

EXAMPLE: DATASOURCE CONFIGURATIONProduction JNDI fragmentTest in-memory fragment

https://leanpub.com/integrationtest/ 53

EXAMPLE: DATASOURCE CONFIGURATION@Beanpublic DataSource ds() { JndiDataSourceLookup lookup = new JndiDataSourceLookup(); lookup.setResourceRef(true); return lookup.getDataSource("jdbc/MyDS");}

@Beanpublic DataSource ds() { org.apache.tomcat.jdbc.pool.DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource(); ds.setDriverClassName("org.h2.Driver"); ds.setUrl("jdbc:h2:~/test"); ds.setUsername("sa"); ds.setMaxActive(1); return ds;}

https://leanpub.com/integrationtest/ 54

FRAGMENT STRUCTURE Main fragment• Repository• Service• etc.

Prod DB fragment Test DB fragment

https://leanpub.com/integrationtest/ 55

TIPSPrevent coupling• Use top-level assembly instead of

fragment referencesPool exhaustion check• Set the maximum number of

connections in the pool to 1Compile-time safety• Use JavaConfig

https://leanpub.com/integrationtest/ 56

NOW, HOW TO TEST?Spring Test• Integration with

widespread testing frameworks

https://leanpub.com/integrationtest/ 57

SAMPLE TESTNG TEST WITH SPRING@ContextConfiguration( classes = { MainConfig.class, TestDataSourceConfig.class })@RunWith(SpringJUnit4ClassRunner.class)public class OrderIT {

@Autowired private OrderService orderService;

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

https://leanpub.com/integrationtest/ 58

TESTING WITH THE DATABASETransactions• Bound to business feature• Implemented on Service

layer•@Transactional

https://leanpub.com/integrationtest/ 59

TRANSACTION MANAGEMENT TIPWhen tests fail•How to audit state?• Spring rollbacks

transactions@Commit

https://leanpub.com/integrationtest/ 60

TRANSACTION MANAGEMENT SAMPLE@ContextConfiguration@Transactional@Commit@RunWith(SpringJUnit4ClassRunner.class)public class OverrideDefaultRollbackSpringTest{

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

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

https://leanpub.com/integrationtest/ 61

END-TO-END TESTING?Testing from the UI layer is fragile•UI changes a lot

URL not so much

https://leanpub.com/integrationtest/ 62

MOCKMVC“Main entry point for server-side Spring MVC test support”

https://leanpub.com/integrationtest/ 63

MOCKMVC SAMPLEmockMvc.perform(get("/")) .andExpect(status().isOk()) .andExpect(view().name("welcome"));

https://leanpub.com/integrationtest/ 64

SPRING BOOT

https://leanpub.com/integrationtest/ 65

SPRING BOOT@AutoConfigureMockMvcInject MockMvc

https://leanpub.com/integrationtest/ 66

SPRING BOOT@SpringBootTest instead of @ApplicationContext

https://leanpub.com/integrationtest/ 67

SPRING BOOT LAYERED TESTSJPA•@DataJpaTest

Web•@WebMvcTest•@MockBean

https://leanpub.com/integrationtest/ 68

Q&A

http://blog.frankel.ch/@nicolas_frankel http://frankel.in/https://git.io/viPPz