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
190

Integration Testing from the Trenches by Nicolas Fränkel

Riga Dev Day

March 13, 2016
Tweet

Transcript

  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, 
 "myWar.war”)
 .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