Introducing LambdaTest: A new Scala Testing Library

Introducing LambdaTest: A new Scala Testing Library

LambdaTest is a new small and clean library for testing Scala code developed by 47 Degrees. Tests can be run either via SBT or directly. The entirety of the code is open source with an Apache 2 license.

View LambdaTest on GitHub or visit the LambaTest microsite

Philosophy

The motivation for building LambdaTest was to provide a simple testing library that’s both easy to understand and easy to extend.

Three philosophical principles drove the new design:

  • Focus on developers. There has been a trend in testing to focus primarily on human readable output targeted at managers, pm’s, and customers. While LambdaTest can certainly be used for this purpose, its primary target audience is developers. Testing should give developers high leverage. This is achieved by treating testing as programming; not just a list of test cases. LambdaTest includes ScalaCheck as a significant step in this direction. Complex testing systems can also be produced by writing Scala that generates the tests.

  • Pure functional Scala. For many years, object-oriented programming has been the dominant methodology. Existing test libraries have focused on testing OO code and are implemented as OO systems. Although not a new idea, a functional methodology (with pure functions operating on immutable data) is now becoming widely accepted in mainstream systems and is dramatically improving code quality. Although LambdaTest can certainly be used to test OO code, it has a focus on providing strong support for testing functional code. Equally important, the implementation of LambdaTest is functional; yielding a clean, easy to understand and extend API.

  • Small, clean, and extensible. Scala testing systems have grown increasingly complex, some have become huge bloatware, with users asking for, and maintainers adding more and more features. This can cause the resulting systems to be increasingly difficult to understand and the complex APIs tricky to extend. LambdaTest takes a different approach with a small, clean core and easy extensibility. The core part of LamdaTest is kept small (< 1K lines of Scala) by providing only basic tests and the infrastructure needed to add a broad range of customizations and extensions.

Small Example

Here is a somewhat artificial example of a very simple LambdaTest test.

import com.fortysevendeg.lambdatest._

class Example extends LambdaTest {

  val act = label("Initial Tests") {
    test("Eq test") {
      assertEq(2 + 1, 3, "Int eq test")
    }
  } +
  label("Simple Tests") {
    test("Assert Test") {
      assertEq(1, 2, "Bad Int eq test") +
      assert(3 == 5 - 2, "should work")
    }
  }
}

When run this produces the following output.

[info] Running demo.Example 
[info] ***** running example
[info] Initial Tests
[info]   Test: Eq test
[info]     Ok: [3] Int eq test (Example.scala Line 11)
[info] Simple Tests
[info]   Test: Assert Test
[info]     Fail: [1 != 2] Bad Int eq test (Example.scala Line 16)
[info]     Ok: should work (Example.scala Line 17)
[info] ***** example: 2 tests 1 failed 0.026 seconds
[success] Total time: 19 s, completed Feb 1, 2017 12:55:31 PM

States and Actions

The LambdaTest API is simple to use and extend because it’s all based on two primary classes.

  • States. The LambdaTest API records testing state in immutable data structures of type LambdaState.

  • Actions. An action is a purely functional transform from one state to another and has type LambdaAct. In the example, simple actions are assert and assertEq. Two actions can be composed into a new action using the infix + operator. A compound action is an action whose body is itself an action. In the example, compound actions are label and test. Note the overall test is itself just an action.

Extensions

There are two ways in which LambdaTest can be customized and extended:

  • New actions. Writing new simple and compound actions is easy.
  • Compose actions. In the example, action composition is quite static. But more dynamic actions can be generated by Scala defs with result type LambdaAct.

While each company/team/project is free to define its own extensions, there are currently three predefined extensions:

  • LambdaTestAsync. Supports asynchronous testing for Akka actors and logs.
  • LambdaTestTime. Supports timing of code.
  • LambdaTestCapture. Allows test output to be directed to an in-memory data structure or stored as Json in files or logs.

Note that each of these extensions is independent and required no modifications to the LambdaTest core thus demonstrating the extension power available in the core.

To Learn More

See the complete LambdaTest documentation for more information and lots of examples.

And keep an eye out for future blog posts covering some of the more advanced features of LambdaTest and follow @47deg.

blog comments powered by Disqus

Ensure the success of your project

47 Degrees can work with you to help manage the risks of technology evolution, develop a team of top-tier engaged developers, improve productivity, lower maintenance cost, increase hardware utilization, and improve product quality; all while using the best technologies.