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

TestContainers: JEEConf 2017

TestContainers: JEEConf 2017

Sergei Egorov

May 27, 2017
Tweet

More Decks by Sergei Egorov

Other Decks in Programming

Transcript

  1. About me • Site Reliability Engineer at • Before: ZeroTurnaround,

    TransferWise, etc… • TestContainers’ co-maintainer • In love with Docker since 2013 @bsideup
  2. Unit testing • Simulation tests are green, yay! • Everything

    is mocked • DB is written by others, why should I test it?
  3. Integration testing https://commons.wikimedia.org/wiki/File:Cd4007.jpg • Jeez, how did it passed the

    Unit testing? • Is it a smoke? @#$%! YES IT IS! • Who knew that 100w soldering gun was a bit too powerful for it?
  4. System testing https://commons.wikimedia.org/wiki/File:UART_8250_Microchip.jpg • Takes a lot of time to

    solder • “Oh no, the power bus is too far away from my microchip!” • Interference between the components
  5. Integration testing Real-world, but isolated testing Spot the issues before

    the real environment Can be run during the development You have to start real databases Should be cross-platform Slower than Unit testing Pros Cons
  6. Docker Compose FTW! redis:
 image: redis
 ports:
 - "6379:6379"
 postgres:


    image: postgres
 ports:
 - "5432:5432"
 elasticsearch:
 image: elasticsearch:5.0.0
 ports:
 - "9200:9200"

  7. No ports randomization redis:
 image: redis
 ports:
 - "6379:6379"
 postgres:


    image: postgres
 ports:
 - "5432:5432"
 elasticsearch:
 image: elasticsearch:5.0.0
 ports:
 - "9200:9200"

  8. TestContainers • http://github.com/testcontainers/testcontainers-java • Wraps docker-java library • Docker environment

    discovery (Win, Mac, Linux) • Will start docker-machine if it’s not started yet • Containers cleanup on JVM shutdown
  9. As simple as PostgreSQLContainer postgresql = new PostgreSQLContainer()
 
 GenericContainer

    redis = new GenericContainer("redis:3")
 .withExposedPorts(6379)
  10. Use case #1: testing of microservices • REST service •

    Java, Spring Boot • Redis and PostgreSQL • Calls some other micro-services
  11. @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT) @ContextConfiguration(initializers = Initializer.class) public abstract class

    AbstractIntegrationTest { @ClassRule public static PostgreSQLContainer postgreSql = new PostgreSQLContainer(); @ClassRule public static GenericContainer redis = new GenericContainer("redis:3.0.6") .withExposedPorts(6379); @ClassRule public static MockServerContainer mockServer = new MockServerContainer(); }
  12. @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT) @ContextConfiguration(initializers = Initializer.class) public abstract class

    AbstractIntegrationTest { @ClassRule public static PostgreSQLContainer postgreSql = new PostgreSQLContainer(); @ClassRule public static GenericContainer redis = new GenericContainer("redis:3.0.6") .withExposedPorts(6379); @ClassRule public static MockServerContainer mockServer = new MockServerContainer(); } Still using all the Spring goodies!
  13. @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT) @ContextConfiguration(initializers = Initializer.class) public abstract class

    AbstractIntegrationTest { @ClassRule public static PostgreSQLContainer postgreSql = new PostgreSQLContainer(); @ClassRule public static GenericContainer redis = new GenericContainer("redis:3.0.6") .withExposedPorts(6379); @ClassRule public static MockServerContainer mockServer = new MockServerContainer(); } External dependencies
  14. public class MockServerContainer<SELF extends MockServerContainer<SELF>> extends GenericContainer<SELF> { public MockServerContainer()

    { super("jamesdbloom/mockserver:latest"); addExposedPorts(8080); } private MockServerClient client; @Override protected void containerIsStarted(InspectContainerResponse containerInfo) { super.containerIsStarted(containerInfo); client = new MockServerClient(getContainerIpAddress(), getMappedPort(getExposedPorts().get(0))); } }
  15. public class MockServerContainer<SELF extends MockServerContainer<SELF>> extends GenericContainer<SELF> { public MockServerContainer()

    { super("jamesdbloom/mockserver:latest"); addExposedPorts(8080); } private MockServerClient client; @Override protected void containerIsStarted(InspectContainerResponse containerInfo) { super.containerIsStarted(containerInfo); client = new MockServerClient(getContainerIpAddress(), getMappedPort(getExposedPorts().get(0))); } }
  16. Use case #2: Docker as Selenium driver • Selenium/Selenide tests

    • No need to install Chrome/Firefox/etc • CI friendly
  17. @Rule public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer() .withDesiredCapabilities(DesiredCapabilities.chrome()) .withRecordingMode(RECORD_ALL, new

    File("target")); RemoteWebDriver driver = chrome.getWebDriver(); driver.get("https://wikipedia.org"); WebElement searchInput = driver.findElementByName("search"); searchInput.sendKeys("Rick Astley"); searchInput.submit(); WebElement otherPage = driver.findElementByLinkText("Rickrolling"); otherPage.click(); boolean expectedTextFound = driver.findElementsByCssSelector("p") .stream() .anyMatch(element -> element.getText().contains("meme")); assertTrue("The word 'meme' is found on a page about rickrolling", expectedTextFound);
  18. @Rule public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer() .withDesiredCapabilities(DesiredCapabilities.chrome()) .withRecordingMode(RECORD_ALL, new

    File("target")); RemoteWebDriver driver = chrome.getWebDriver(); driver.get("https://wikipedia.org"); WebElement searchInput = driver.findElementByName("search"); searchInput.sendKeys("Rick Astley"); searchInput.submit(); WebElement otherPage = driver.findElementByLinkText("Rickrolling"); otherPage.click(); boolean expectedTextFound = driver.findElementsByCssSelector("p") .stream() .anyMatch(element -> element.getText().contains("meme")); assertTrue("The word 'meme' is found on a page about rickrolling", expectedTextFound); import org.openqa.selenium.remote.RemoteWebDriver;
  19. @Rule public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer() .withDesiredCapabilities(DesiredCapabilities.chrome()) .withRecordingMode(RECORD_ALL, new

    File("target")); RemoteWebDriver driver = chrome.getWebDriver(); driver.get("https://wikipedia.org"); WebElement searchInput = driver.findElementByName("search"); searchInput.sendKeys("Rick Astley"); searchInput.submit(); WebElement otherPage = driver.findElementByLinkText("Rickrolling"); otherPage.click(); boolean expectedTextFound = driver.findElementsByCssSelector("p") .stream() .anyMatch(element -> element.getText().contains("meme")); assertTrue("The word 'meme' is found on a page about rickrolling", expectedTextFound);