Testing With Kotlin #1

Spek framework contributor Laura Kogler demonstrates the current state of Kotlin testing frameworks and discusses expected further advancements in testing support.


Introduction (0:00)

My name is Laura, I’m an engineer at Pivotal Labs. I’m an Android developer and that’s how I got started in Kotlin. I’m also a test-driven development evangelist. I love TDD and testing, and it’s a big part of what we do at Pivotal Labs. At Pivotal Labs, we actually maintain a number of open-source test frameworks including Jasmine for Javascript, and Cedar for Objective-C.

Kotlin Over J-Unit

J-Unit tests have a flat structure, and you can’t nest tests in any useful way. Having learned TDD in Ruby using RSpec, you can group your tests and have shared setup and teardown. When I found Kotlin, I wondered if anyone has written a BDD test framework for Kotlin.

Demo (3:25)

We created a test class, and it has to inherit from the Spek class here, and then we get to pass in this block. And this block is where we can sort of define our test structure. So I started it out with this describe block:

class TestSource : Spek({
    describe("playing rock paper scissiors") {
      val game = RockPaperScissors()
    }
})

I instantiate a new rock-paper-scissors game. And then I’m gonna try and describe some different scenarios that we might have when we’re playing rock-paper-scissors. We can do what’s called a context:

class TestSource : Spek({
    describe("playing rock paper scissiors") {
      val game = RockPaperScissors()

      context("player one plays rock") {
        beforeEach {
          game.recordMove(player = Player.ONE, move = Move.ROCK)
        }

        context("and player two plays scissors") {
          beforeEach {
            game.recordMove(player = Player.TWO, move = Move.SCISSORS)
          }

          it("declares player one the winner") {
            assertEquals("Player One wins!", game.getResult())
          }
        }
      }
    }
})

So you can use context or describe, or actually there’s even a few more synonyms that are available, which are given and on. They’re all aliases for the same thing, which just lets you define a block of context in your test. So, in this context, suppose player one plays rock. To define a setup for this test, we use beforeEach.

Note that our contexts are arbitrarily nestable, and we can define as many layers as we would like. The meat of it is when you use assertEquals, and test the game result.

What this lets you do is define complex scenarios, in a way that’s very readable and legible.

New Features (8:05)

Incomplete Feature

Suppose you’re working on a feature which isn’t complete. You can just put an x in front of it, and it will pend out the tests. The test won’t run, but it integrates with J-Unit along with the infrastructure.

xcontent("when player one plays rock") {
  beforeEach {
    game.recordMove(player=Player.ONE, move=Move.ROCK)
  }
}

Running a Single Test

To run a single test, you can add an f to run a focused test:

fit(“declares player two the winner”) { assertEquals(“Player Two wins!”, game.getResults()) }

The IDE will then only run the one I have focused.

Commandline runner

Another feature of Spek is a command line runner which is completely independent of J-Unit. The way we’re running it in the IDE is it has a J-Unit runner that hooks into the J-Unit infrastructure, and can integrate with any tooling that uses J-Unit.

If you dislike J-Unit, you can use its own runner on the commandline, which has basic reporting including a text output and HTML output mode. Failures show up in red, pending tests show up in yellow, and there’s some summary reporting at the bottom.

Conclusion

That’s pretty much the basic feature set of Spek at this point. I think there’s a lot we could do with Spek in the future that I’d really like to see. Here’s my Spek wish list:

  • Robolectric Integration
  • Spring Support
  • Improved CLI
  • Better IDE Integration

If others have ideas for improving Spek, pull requests are welcome.


Laura Kogler

Laura Kogler

Laura Kogler is a scientist turned software engineer based in the San Francisco Bay Area. In her free time, she enjoys making pretty things (and sometimes setting them on fire).