Typesafe Activator

Test Patterns in Scala!

Test Patterns in Scala!

eptx
Source
November 5, 2013
basics scala starter testing

Scala is a great language to test applications, integrations, services, and more. This app gives simple and intermediate examples of how to get started.

How to get "Test Patterns in Scala!" on your computer

There are several ways to get this template.

Option 1: Choose test-patterns-scala in the Typesafe Activator UI.

Already have Typesafe Activator (get it here)? Launch the UI then search for test-patterns-scala in the list of templates.

Option 2: Download the test-patterns-scala project as a zip archive

If you haven't installed Activator, you can get the code by downloading the template bundle for test-patterns-scala.

  1. Download the Template Bundle for "Test Patterns in Scala!"
  2. Extract the downloaded zip file to your system
  3. The bundle includes a small bootstrap script that can start Activator. To start Typesafe Activator's UI:

    In your File Explorer, navigate into the directory that the template was extracted to, right-click on the file named "activator.bat", then select "Open", and if prompted with a warning, click to continue:

    Or from a command line:

     C:\Users\typesafe\test-patterns-scala> activator ui 
    This will start Typesafe Activator and open this template in your browser.

Option 3: Create a test-patterns-scala project from the command line

If you have Typesafe Activator, use its command line mode to create a new project from this template. Type activator new PROJECTNAME test-patterns-scala on the command line.

Option 4: View the template source

The creator of this template maintains it at https://github.com/eptx/activator-test-patterns-scala#master.

Option 5: Preview the tutorial below

We've included the text of this template's tutorial below, but it may work better if you view it inside Activator on your computer. Activator tutorials are often designed to be interactive.

Preview the tutorial

Start Testing!

You've just created a basic Scala application and a bunch of tests to show off some of Scala's power and some common test patters. Here are some files to start with:

Note that when you run the tests some will intentionally fail to show certain patterns and features.

Test01

See src/test/scala/scalatest/Test01.scala

This is a simple test class that imports and uses ScalaTest FunSuite. More info on ScalaTest. Notice that there are 2 tests. Each is a function with a single parameter, the test name, and a body of code with a single assert statement. What this means is that you have a test that follows the DRY principle. You define the test name and it ID's the test as well. You don't have to define a test method name and title text in separately as in some other frameworks. Nice!

You can run this test from your favorite IDE or via command line within SBT.

sbt>test-only scalatest.Test01

Test02

See src/test/scala/scalatest/Test02.scala

Some more simple tests but using assert with triple equal signs "===". Run the test after changing the expected value to be different than the actual value. Notice the output for the failed test and how it shows the difference between what was expected and the actual as in assert(expected_value === actual_value).

Test03

See src/test/scala/scalatest/Test03.scala

In Test03 we introduce the "intercept" feature in ScalaTest. This is useful when you want to test the expectation of failure. intercept[IndexOutOfBoundsException]{} wraps code that should fail. In the first test, commented out, the code does not throw an IndexOutOfBounds Exception, so the test fails. In the second test, the code throws the exception as expected, the test passes.

Test04

See src/test/scala/scalatest/Test04.scala

In Test04 we see some of Scala's parallel processing ease. We create some test accounts then process them in serial in the first test, then in parallel in the second test. The parallel processing in the second test is enabled using parallel extension .par on the accounts collection. I'm using a machine with 4 cores. With a small sample set of say 20 accounts I get a 2.5x boost in parallel. With a larger set of say 100 accounts I get nearly a 4x boost parallel. I've written plenty of concurrent and parallel code with threads and thread pools...but never this simple.

Test05

See src/test/scala/scalatest/Test05.scala

In Test05 we start to have some fun with Data Driven Testing and Rule Composition.

Note: Expect failures in this test to show capability.

Data Driven Testing: We create some accounts and in a foreach loop a test for each account. Each test gets its own name. I could use .par as in the previous example to create test in parallel. Not much gate with that however in this case. Note that tests by default execute in parallel unless in build.sbt you set parallelExecution in Test := false. What if you had entities within entities within entities to test...could you nest loops for test creation? You bet. Data Driven testing is a very powerful way to get the coverage you need. Scala and ScalaTest provide a simple way to leverage that power.

Rule Composition: Ever find yourself re-typing the same set asserts over and over? Let's define some Account Rules as functions and then combine them with boolean operators. You can imagine creating libraries of compliance rules and then combining them into much more complex boolean tree combinations as needed. Oh yeah, and with all those rules...and all the data driven scenarios...you get lots of combinations. Let's test in parallel. The serial output of running tests in parallel can be confusing. At some point it makes sense to post the test results to a server using a ScalaTest Custom Reporter. Then tests can run fast and you can group, sort, filter, etc. as needed for analysis.

withClue: This helps you customize what information you provide for the particular audience or just to narrow down test failure searching.

Test06 and Test07

See

Here you see how use ScalaTest in a specs-like approach. The example is taken from their site. It shows the flexibility of ScalaTest to support testing in multiple paradigms. Also see the example of using Specs2, another great Scala testing framework. No problem using one, the other, or both in your testing

Test08

See src/test/scala/scalatest/Test08.scala

Here you see how use Selenium to automate otherwise tedious, error-prone, inconsistent browser testing. This example uses the ScalaTest Selenium DSL. But you can also use the standard Java API. This test a headless brower HtmlUnitDriver for speed. However, you can change to one of several browser drivers, such as FirefoxDriver, to open and automate a FireFox browser. You could also incorporate custom reporting with this that snaps and stores a browser screen-shot on test failure.

Test09

See src/test/scala/scalatest/Test09.scala

Actors are a very powerful part of the Scala platform to easily enable scalable, reliable, performant systems. Debugging concurrent, parallel, distributed systems can be a difficult task. ScalaTest and the Akka TestKit can help with that.

In this test class you'll see how WordSpec in ScalaTest can be used to test a simple Echo Actor that returns the message sent to it. You'll also see a more interesting actor called GeoActor that, given an address via the Address case class message, returns the lat-lon coordinates for that address. In this case the actors are embedded in the object Setup. In a real system these would be in a separate library. Note that these actors are running local in the same JVM instance as the tests. However, in a real test automation effort they may be running on a separate system including a cloud instance.

Test10

See src/test/scala/scalatest/Test10.scala

Reactive programming is an interesting approach with benefits in many solution spaces. Basically, variables automatically update themselves when values of other dependent variables change. So in this example variable "c" depends-on "a" and "b". If a or b change, c updates itself. Rather than having variables a and b track their "child" dependencies, the Rx library enables c to track its "parent" dependencies. Given this ability, the variables participate in a more event-driven approach. This is especially useful in UI programming where multiple UI elements are bound to a single variable and that variable may be updated in many ways.

So here's another example of kicking the tires on a library Scala.Rx. A future update here will likely spin up a ScalaFX UI demo. Stay tuned...

Test11

See src/test/scala/scalatest/Test11.scala

Let's kick the tires on a popular Scala web library called Spray. In this test we spin up an async, actor-based server and then use a client with futures to exercise our simple REST API. Think about how to expand this test to add protected server resources and use basic authentication on the client to test access.

System integration or full solution specification testing requires connecting 2 or more systems in a meaningful way to drill through the whole request-response handling chain. For example, your solution may have a database system, an application, a policy-enforcement-point proxy, and a browser client. You can elect to wait until they are all up and running and in sync with the same features, but with such late integration testing you run the risk of misaligned systems. Instead, teams can independently work on implementing specs and test smaller integrations early and more frequently until the whole system in ready for solution testing.

In your tests, you can spin up and connect to disparate systems to test integration. This test spins up a server and a client but just as well could spin up different or more systems to test. Note the beforeAll function kicks off "Server" and afterAll shuts it down. ScalaTest allows such "harnessing" per test or across the test class. You can create shared test fixtures as well.

Test12

See src/test/scala/scalatest/Test12.scala

Need to access a database in your test? Of course Scala database access via JDBC or other Java ORMs is available. But take a look at this Slick example and a new, clean way to access your database. In a single test we create and populate an in-memory SQL database, insert data, query data, and test the results. Think about how you might harness database access across tests. Now think about creating data driven tests that exercise UI, REST, business logic, and database for full integration and solution testing. Very powerful! For more info, check out Slick from TypeSafe.

comments powered by Disqus