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

Integration Testing from the Trenches by Nicolas Fränkel

388bd0ce1b0edcbdd87bbcd4d9e7772c?s=47 Riga Dev Day
March 13, 2016
120

Integration Testing from the Trenches by Nicolas Fränkel

388bd0ce1b0edcbdd87bbcd4d9e7772c?s=128

Riga Dev Day

March 13, 2016
Tweet

Transcript

  1. INTEGRATION TESTING FROM THE TRENCHES @NICOLAS_FRANKEL

  2. ME, MYSELF AND I h0ps://leanpub.com/integraContest/ 2

  3. FROM THE BOOK h0ps://leanpub.com/integraContest/ 3

  4. GENERALITIES INTEGRATION TESTING FROM THE TRENCHES 4 h0ps://leanpub.com/integraContest/

  5. 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
  6. 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
  7. EXAMPLE Ø Let’s take a prototype car h0ps://leanpub.com/integraContest/ 7

  8. UNIT TESTING Ø Akin to tes?ng each nut and bolt separately

    h0ps://leanpub.com/integraContest/ 8
  9. INTEGRATION TESTING Ø Akin to going on a test drive h0ps://leanpub.com/integraContest/

    9
  10. 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
  11. 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
  12. REMINDER: TEST DOUBLES Ø Dummy Ø Mock Ø Stub Ø Spy Ø Fake h0ps://leanpub.com/integraContest/ 12

  13. 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
  14. 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
  15. TESTING IS ABOUT ROI Ø Integra?on Tes?ng • Test nominal cases h0ps://leanpub.com/integraContest/

    15
  16. INTEGRATION TESTING ISSUES INTEGRATION TESTING FROM THE TRENCHES 16 h0ps://leanpub.com/integraContest/

  17. INTEGRATION TESTS CHALLENGES Ø Slow Ø Fragile Ø Hard to diagnose h0ps://leanpub.com/integraContest/ 17

  18. Y U SLOW? Ø Use infrastructure resources Ø Use container h0ps://leanpub.com/integraContest/ 18

  19. COPING WITH SLOWNESS Ø Separate Integra?on Tests from Unit Tests h0ps://leanpub.com/integraContest/

    19
  20. 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
  21. HOW TO SEPARATE? Ø Depends on the build tool • Ant • Maven

    • Gradle • Something else? h0ps://leanpub.com/integraContest/ 21
  22. REMINDER: MAVEN LIFECYCLE h0ps://leanpub.com/integraContest/ 22

  23. MAVEN SUREFIRE PLUGIN Ø Bound to the test phase Ø Runs by

    default • *Test • Test* • *TestCase h0ps://leanpub.com/integraContest/ 23
  24. MAVEN FAILSAFE PLUGIN Ø “Copy” of Surefire Ø Different defaults • *IT • IT*

    • *ITCase h0ps://leanpub.com/integraContest/ 24
  25. 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
  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> h0ps://leanpub.com/integraContest/ 26
  27. CONTINUOUS INTEGRATION Ø Unit Tests run at each commit Ø Integra?on Tests

    run “regularly” • Daily • Hourly • Depending on the context h0ps://leanpub.com/integraContest/ 27
  28. Y U FRAGILE? Ø Usage of infrastructure resources • External • MulCple h0ps://leanpub.com/integraContest/

    28
  29. INFRASTRUCTURE RESOURCES Ø File system Ø Time Ø Databases Ø Web Services Ø Mail servers

    Ø FTP Servers Ø etc. h0ps://leanpub.com/integraContest/ 29
  30. 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
  31. DATABASES: COPING WITH FRAGILITY h0ps://leanpub.com/integraContest/ 31 Ø Test the Service layer

    • Mock the repository Ø Test the Repository layer • Mock the database???
  32. DATABASES: COPING WITH FRAGILITY Ø Use Fakes under your control h0ps://leanpub.com/integraContest/

    32
  33. 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
  34. TRADE-OFF h0ps://leanpub.com/integraContest/ 34 Ø The closer to the “real” infrastructure, the

    more complex the setup
  35. 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
  36. 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
  37. WEB SERVICES: COPING WITH FRAGILITY Ø Use Fakes under your control

    h0ps://leanpub.com/integraContest/ 37
  38. 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
  39. 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
  40. FAKE SOAP WEB SERVICES h0ps://leanpub.com/integraContest/ 40 Ø Possible with Spark • But

    not efficient • Remember about ROI
  41. SMARTBEAR SOAPUI h0ps://leanpub.com/integraContest/ 41

  42. SMARTBEAR SOAPUI Ø The framework to test SOAP WS • Has a

    GUI • Good documentaCon • Understands •  AuthenCcaCon •  Headers •  Etc. h0ps://leanpub.com/integraContest/ 42
  43. 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
  44. 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
  45. 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
  46. 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
  47. IN-CONTAINER TESTING INTEGRATION TESTING FROM THE TRENCHES 47 h0ps://leanpub.com/integraContest/

  48. INTEGRATION TESTING h0ps://leanpub.com/integraContest/ 48 Ø Collabora?on between classes Ø Boundaries with external

    dependencies Ø What did we forget?
  49. DEPENDENCIES h0ps://leanpub.com/integraContest/ 49 Ø The most important dependency is the container!

    • Spring • Java EE • ApplicaCon server
  50. 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?
  51. 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
  52. EXAMPLE: DATASOURCE CONFIGURATION h0ps://leanpub.com/integraContest/ 52 Ø Produc?on JNDI fragment Ø Test in-

    memory fragment
  53. 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
  54. FRAGMENT STRUCTURE Ø  Main fragment • Repository • Service • etc. Ø  Prod

    DB fragment Ø  Test DB fragment h0ps://leanpub.com/integraContest/ 54
  55. 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
  56. NOW, HOW TO TEST? h0ps://leanpub.com/integraContest/ 56 Ø Spring Test • IntegraCon with

    widespread tesCng frameworks
  57. SPRING TESTNG INTEGRATION h0ps://leanpub.com/integraContest/ 57 Ø AbstractTestNGSpringContextT ests •  AbstractTransacConalTestNGSprin gContextTests

    Ø Configurable context fragments •  @ContextConfiguraCon Ø Inject any bean in the test class
  58. 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
  59. TESTING WITH THE DATABASE Ø Transac?ons • Bound to business feature • Implemented

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

    • Spring rollbacks transacCons Ø @Transac?onConfigura? on • defaultRollback = false h0ps://leanpub.com/integraContest/ 60
  61. 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
  62. THE JAVA EE WORLD Ø Java EE has unique challenges • CDI

    has no explicit wiring • Different applicaCon servers h0ps://leanpub.com/integraContest/ 62
  63. 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
  64. 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
  65. 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
  66. 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
  67. 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
  68. 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
  69. Q&A h0ps://leanpub.com/integraContest/ 69 hpps://goo.gl/mXv7ZE @nicolas_frankel hpp://frankel.in/