Skip to content
Paul Rogers edited this page Nov 26, 2016 · 26 revisions

Testing Tips

Drill makes extensive use of JUnit and other libraries for testing. This page provides pointers to the information you need to work with Drill tests. We don't repeat that information; you will want to follow the links and read the original material to get a complete understanding of the libraries that Drill uses.

Caveat: information here about Drill is "reverse engineered" from the code; this page has not yet had the benefit of insight from the developers who created Drill's test structure.

JUnit

Most of us know the basics of JUnit. Drill uses many advanced features that we mention here. Drill uses JUnit 4, currently version 4.11.

Good references:

JUnit/Hamcrest Idioms

Drill tests use the JUnit 4 series that uses annotations to identify tests. Drill makes use of the "Hamcrest" additions (which seem to have come from a separate project, later merged into JUnit, hence the strange naming.) Basic rules:

  • All tests are packaged into classes, all classes start or end with the word "Test". In Drill, most tests use the prefix format: "TestMumble".
  • Test methods are indicted with @Test.
  • Disabled tests are indicated with @Ignore("reason for ignoring")
  • Tests use "classic" JUnit assertions such as assertEquals(expected,actual,opt_msg).
  • Tests also use the newer "Hamcrest" assertThat formulation. The Hamcrest project provided a system based on assertions and matchers that are quite handy for cases that are cumbersome with the JUnit-Style assertions.
  • Many tests make use of the test fixture annotations. These include methods marked to run before or after all tests in a class (@BeforeClass and @AfterClass) and those that run before or after each test (@Before and @After).
  • The base DrillTest class uses the ExceptionRule to declare that no test should throw an exception.
  • Few Drill tests verify exceptions directly. But, the cleanest way appears to still be the try/catch idiom.
  • Drill tests have the potential to run for a long time, or hang, if thing go wrong. To prevent this, Drill tests use a timeout. The main Drill test base class, DrillTest uses a timeout rule to set a default timeout of 50 seconds:
@Rule public final TestRule TIMEOUT = TestTools.getTimeoutRule(50000);
  • Individual tests (override?) this rule with the timeout parameter to the Test annotation @Test(timeout=1000). This form an only decrease (but not increase) the timeout set by the timeout rule.
  • Tests that need a temporary file system folder use the @TemporaryFolder rule.
  • The base DrillTest class uses the TestName rule to make the current test name available to code: System.out.println( TEST_NAME );.

Additional Resources

Some other resources that may be of interest moving forward:

  • JUnitParams - a cleaner way to parameterize tests.
  • Assumptions for declaring dependencies and environment setup that a test assumes.
  • JUnit Rules may occasionally be helpful for specialized tests.
  • Categories to, perhaps, identify those "smoke" tests that should be run frequently, and a larger, more costly set of "full" tests to be run before commits, etc.
  • [System Rules][http://stefanbirkner.github.io/system-rules/] - A collection of JUnit rules for testing code that uses java.lang.System such as printing to System.out, environment variables, etc.
  • The Stopwatch rule added in JUnit 4.12 to measure the time a test takes.
  • the DisableonDebug rule added in JUnit 4.12 which can turn off other rules when needed in a debug session (to prevent, say, timeouts, etc.)

JMockit

Drill is built as a highly-coupled network of classes. That is, each part of Drill directly depends on many other parts. This structure reflects the complexity of the problem that Drill solves, but the resulting tight coupling works against us when testing components in isolation. (The very definition of tight coupling is that components cannot be easily isolated.)

A solution to this problem is "mocking": the idea that we substitute an "artificial" dependency for the real one. Drill uses the Mockit framework for this purpose.

References:

  • JMockit Tutorial - A comprehensive guide to the purpose and operation of JMockit.

Mockito

Drill depends on the Mockito framework. (Need to find & document usages.)

Drill Test Structure

Maven

The root Drill pom.xml declares a test-time dependency on JUnit 4.11:

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

Since this dependency is in the root POM, there is no need to add it to the POM files of each Drill module.

Eclipse

Using JUnit with Eclipse is trivial:

  • To run all tests in a class, select the class name (or ensure no text is selected) and use the context menu option Debug As... --> JUnit.
  • To run a single test, select the name of the test method, and invoke the same menu command.

Using JMockit is a bit more fussy. See the Getting Started page for info.

IntelliJ

Hey IntelliJ users, what advice can we put here?

Clone this wiki locally