java day kharkiv - integration testing from the trenches rebooted
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