Tag Archives: sbt

Easy suite tagging with ScalaTest 2.0

If you are using ScalaTest 1.x and you need to tag some tests to make them easily skippable, you have to tag each method separately:

class MySpec extends FlatSpec with ShouldMatchers {

  it should "pass this exercise" taggedAs SlowTest in {
    // ...
  }

  it should "pass another exercise" taggedAs SlowTest in {
    // ...
  }
}

This approach has two major flaws:

  • It’s easy to forget about your tag.
  • If you use BeforeAndAfterAll, the code in beforeAll() will execute anyway. It’s possible that in slow tests this code will initialize some infrastructure (for example bring up the database) which is exactly the thing we want to avoid when we tag our tests.

One solution is to use nested suites and keep the beforeAll() initialization in the master suite. This requires some additional plumbing if we want to execute suites individually. However, with ScalaTest 2.0, we have a better option, allowing us to keep things simple and flexible: suite tagging.

In short, you can now annotate a whole suite, and then run tests with your annotation in exclusion rules. This will eliminate the whole suite with its beforeAll(), afterAll() and any other blocks surrounding method invocations.

How to prepare a tag

Just create a simple Java annotation like following.

package tags;

@org.scalatest.TagAnnotation
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface RequiresDb {
}

Remember – it has to be plain Java annotation. If you try to use Scala techniques like extending StaticAnnotation, then this will probably not work.
Now you can annotate your suite:

@RequiresDb
class MySpec extends FlatSpec with Matchers {
  // ...
}

That’s it, execute tests using this SBT command:

test-only * -- -l tags.RequiresDb

and it should do the trick. Note: use full class name, here it was tags.RequiresDb, where “tags” is just the Java package name.
Moreover, you can use a cool technique from this blog post and replace this pretty ugly incantation with simple

local:test

If you want a full working example, check my GitHub for one.

Advertisements