Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Integration Testing from the Trenches by Nicolas Fränkel

Riga Dev Day
March 13, 2016

Integration Testing from the Trenches by Nicolas Fränkel

Riga Dev Day

March 13, 2016


  1. TESTING? Ø Unit Tes?ng Ø Muta?on Tes?ng Ø GUI Tes?ng Ø Performance Tes?ng • 

    Load TesCng •  Stress TesCng •  Endurance TesCng Ø Security Tes?ng Ø etc. h0ps://leanpub.com/integraContest/ 5
  2. UNIT VS. INTEGRATION TESTING Ø Unit Tes?ng • TesCng a unit in

    isolaCon Ø Integra?on Tes?ng • TesCng the collaboraCon of mulCple units h0ps://leanpub.com/integraContest/ 6
  3. UNIT + INTEGRATION TESTING Ø Not exclusive but complementary • Take 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? h0ps://leanpub.com/integraContest/ 10
  4. SYSTEM UNDER TEST Ø SUT is what get tested Ø Techniques from

    Unit Tes?ng can be re-used • Dependency InjecCon • Test doubles h0ps://leanpub.com/integraContest/ 11
  5. TESTING IS ABOUT ROI Ø The larger the SUT • The more

    fragile the test • The less maintainable the test • The less the ROI h0ps://leanpub.com/integraContest/ 13
  6. TESTING IS ABOUT ROI Ø Tests have to be organized in

    a certain way • The bigger the SUT • The less the number of tests h0ps://leanpub.com/integraContest/ 14
  7. INTEGRATION TESTS ARE STILL SLOW Ø Separa?ng IT doesn’t make them

    faster Ø But errors can be uncovered faster • Fail fast • It will speed tesCng h0ps://leanpub.com/integraContest/ 20
  8. HOW TO SEPARATE? Ø Depends on the build tool • Ant • Maven

    • Gradle • Something else? h0ps://leanpub.com/integraContest/ 21
  9. MAVEN SUREFIRE PLUGIN Ø Bound to the test phase Ø Runs by

    default • *Test • Test* • *TestCase h0ps://leanpub.com/integraContest/ 23
  10. MAVEN FAILSAFE PLUGIN Ø One goal per lifecycle phase • pre-integration-test • integration-test

    • post-integration-test • verify Ø Must be bound explicitly h0ps://leanpub.com/integraContest/ 25
  11. 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> h0ps://leanpub.com/integraContest/ 26
  12. CONTINUOUS INTEGRATION Ø Unit Tests run at each commit Ø Integra?on Tests

    run “regularly” • Daily • Hourly • Depending on the context h0ps://leanpub.com/integraContest/ 27
  13. TIME/FILE SYSTEM: COPING WITH FRAGILITY h0ps://leanpub.com/integraContest/ 30 Ø Use Dependency Injec?on

    Ø Use abstrac?ons • e.g. java.nio.file.Path instead of java.util.File
  14. DATABASES: COPING WITH FRAGILITY h0ps://leanpub.com/integraContest/ 31 Ø Test the Service layer

    • Mock the repository Ø Test the Repository layer • Mock the database???
  15. ORACLE DATABASE USE-CASE h0ps://leanpub.com/integraContest/ 33 Ø Use an in-memory data source

    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
  16. MANAGING THE GAP RISK h0ps://leanpub.com/integraContest/ 35 Ø In-memory databases are easy

    to setup Ø h2 is such a database • CompaCbility modes for most widespread DB •  jdbc:h2:mem:test; MODE=Oracle
  17. WEB SERVICES: COPING WITH FRAGILITY h0ps://leanpub.com/integraContest/ 36 Ø Web Services as

    infrastructure resources • Hosted on-site • Or outside Ø Different architectures • REST(ful) • SOAP
  18. FAKE RESTFUL WEB SERVICES h0ps://leanpub.com/integraContest/ 38 Ø Spark • Micro web framework

    • A la Sinatra • Very few lines of code • Just serve staCc JSON files
  19. 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!!!"; }); } } h0ps://leanpub.com/integraContest/ 39
  20. SMARTBEAR SOAPUI Ø The framework to test SOAP WS • Has a

    GUI • Good documentaCon • Understands •  AuthenCcaCon •  Headers •  Etc. h0ps://leanpub.com/integraContest/ 42
  21. SOAPUI USAGE Ø Get WSDL •  Either online •  Or from

    a file Ø Create MockService •  Cra\ the adequate response Ø Run the service Ø Point the dependency to localhost h0ps://leanpub.com/integraContest/ 43
  22. CHALLENGES TO THE PREVIOUS SCENARIO Ø Craj 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
  23. SOAPUI API 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(); h0ps://leanpub.com/integraContest/ 45
  24. FAKING WEB SERVICE IN REAL-LIFE Ø Use the same rules as

    for UT • Keep validaCon simple • Test one thing Ø Keep setup simple • Don’t put complex logic • OK to duplicate setup in each test •  Up to a point Author: I, rolf B h0ps://leanpub.com/integraContest/ 46
  25. SPRING CONFIGURATION TESTING h0ps://leanpub.com/integraContest/ 50 Ø So far, we can test:

    • Beans whose dependencies can be mocked • Beans that depend on fake resources Ø What about the configura?on?
  26. DESIGNING TESTABLE CONFIGURATION h0ps://leanpub.com/integraContest/ 51 Ø Configura?on cannot be monolithic • Break

    down into fragments • Each fragment contains a set of either •  Real beans •  Fake beans
  27. EXAMPLE: DATASOURCE CONFIGURATION <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> h0ps://leanpub.com/integraContest/ 53
  28. FRAGMENT STRUCTURE Ø  Main fragment • Repository • Service • etc. Ø  Prod

    DB fragment Ø  Test DB fragment h0ps://leanpub.com/integraContest/ 54
  29. TIPS Ø Prevent coupling • Use top-level assembly instead of fragment references

    Ø Pool exhaus?on check • Set the maximum number of connecCons in the pool to 1 Ø Compile-?me safety • Use JavaConfig h0ps://leanpub.com/integraContest/ 55
  30. SPRING TESTNG INTEGRATION h0ps://leanpub.com/integraContest/ 57 Ø AbstractTestNGSpringContextT ests •  AbstractTransacConalTestNGSprin gContextTests

    Ø Configurable context fragments •  @ContextConfiguraCon Ø Inject any bean in the test class
  31. 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(...) } } h0ps://leanpub.com/integraContest/ 58
  32. TESTING WITH THE DATABASE Ø Transac?ons • Bound to business feature • Implemented

    on Service layer • @Transactional h0ps://leanpub.com/integraContest/ 59
  33. TRANSACTION MANAGEMENT TIP Ø When tests fail • How to audit state?

    • Spring rollbacks transacCons Ø @Transac?onConfigura? on • defaultRollback = false h0ps://leanpub.com/integraContest/ 60
  34. TRANSACTION MANAGEMENT SAMPLE @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() { ... } } h0ps://leanpub.com/integraContest/ 61
  35. THE JAVA EE WORLD Ø Java EE has unique challenges • CDI

    has no explicit wiring • Different applicaCon servers h0ps://leanpub.com/integraContest/ 62
  36. DEPLOY ONLY WHAT YOU WANT Ø Standalone API to deploy only

    resources relevant to the test • Just pick and choose Ø Maven Integra?on • Gradle too… h0ps://leanpub.com/integraContest/ 63
  37. 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"); h0ps://leanpub.com/integraContest/ 64
  38. MAVEN INTEGRATION SAMPLE File[] libs = Maven.resolver() .loadPomFromFile("pom.xml") .importDependencies(COMPILE, RUNTIME)

    .resolve() .withTransitivity().asFile(); ShrinkWrap.create(WebArchive.class, 
 .addAsLibraries(libs); h0ps://leanpub.com/integraContest/ 65
  39. DIFFERENT APPLICATION SERVERS Ø Abstrac?on layer to •  Download •  Deploy

    applicaCons •  Test Ø Container adapters •  TomEE •  JBoss •  Weld •  etc. Ø Full Maven integra?on h0ps://leanpub.com/integraContest/ 66
  40. 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(...); } } h0ps://leanpub.com/integraContest/ 67
  41. ARQUILLIAN CONFIGURATION SAMPLE <arquillian xmlns="http://jboss.org/schema/ arquillian" xmlns:xsi="..." xsi:schemaLocation=" http://jboss.org/schema/arquillian http://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> h0ps://leanpub.com/integraContest/ 68