Tests in Play Framework

on waitingforcode.com

Tests in Play Framework

Until now we were writing our store without tests, in the goal to quickly discover some of Play basic features. However, a code without tests is as a car without wheels. It will exist but will be driveless. The code without tests exists too, but it less evolutionary than the code well covered by the tests.

As you imagine, in this article we'll focus on testing aspect of Play Framework. In the first one we'll describe the tests launching process. At the second part we'll discover how to configure different environments of development.

Launching tests in Play Framework

While Play setups new project, it puts some sample tests inside /test directory. Let's begin by launching these natively created tests. To do that, we need to place into our project base directory. After that, we enter to activator console by calling ./activator. Now we should be in the prompt of [testApp]. To launch all test cases, we use test command. However, sometimes a very strange message can appear as a result of it:

# testOnly * command means exactly the same as test - it'll execute all tests; 
# to execute one test, you should replace * by the name of test class
[testApp] $ testOnly *
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for test:testOnly

This result is probably because of Play's cache. To remedy to this problem, you should invoke ./activator clean before entering to Activator's prompt. The clean command will delete temporary files including bytecode cache. If you're using other version than 2.3, probably the reason of you problem can be associated with bad configured JUnit interface. If we relaunch tests now, we should receive following message:

# tests will fail because of JPA configuration problem - we don't take care about it for now
[info] Total for test IntegrationTest
[info] Finished in 0.009 seconds
[info] 1 tests, 1 failures, 0 errors
# ...
[info] Total for test ApplicationTest
[info] Finished in 0.002 seconds
[info] 2 tests, 1 failures, 0 errors

Activator has some other interesting features about testing. If you launch show test:sources command, you'll see which are Java classes present in the /test folder:

# Lists all Java files, even if they doesn't contain JUnit test cases as NotJUnitTestClass here
[testApp] $ show test:sources
[info] ArrayBuffer(/home/bartosz/workspace/playApp/testApp/test/IntegrationTest.java, /home/bartosz/workspace/playApp/testApp/test/NotJunitTestClass.java, /home/bartosz/workspace/playApp/testApp/test/ApplicationTest.java, /home/bartosz/workspace/playApp/testApp/test/controllers/CategoryControllerTest.java)
[success] Total time: 0 s, completed Jul 26, 2014 8:24:16 AM

Another interesting command is show test:resourceDirectory which displays the resources directory for test environment. If you've already worked with Maven, you certainly remember that you can specify some resource files inside resources directory from the test directory. You can make the same thing with Play Framework:

[testApp] $ show test:resourceDirectory
[info] /home/bartosz/workspace/playApp/testApp/test/resources

If you want to check which files are considered as test resources, anything simpler than a show test:resources command:

[testApp] $ show test:resources
[info] List(/home/bartosz/workspace/playApp/testApp/test/resources, /home/bartosz/workspace/playApp/testApp/test/resources/resources_test_file.txt)

We've already seen which options used to launch all tests (simple test command) or only one test (testOnly classToTest). But what we can do to check only failing tests ? To do that we can use testQuick command which should print exactly the same results as in the first output from this part of article.

Setup test environment in Play Framework

It's always useful to have an environment destined to tests execution. By environment we understand for example writable test database or different configuration for some of application parts. Thanks to it we can be sure that development and production environments won't be modified (even by accident) by operations launched in test cases (in the case of integration tests). In Play Framework, as in Spring, we also can setup a test environment.

In current (2.3) version of Play it's not so simple to submit different configuration in test environment. Normally you should be able to achieve that with -Dconfig.file=conf/myConfig.conf parameter added to Activator launch command. Unfortunately it's not the case because even if you start Activator with this argument, the customized configuration file is not taken in consideration. One trick allowing us to add separate options to test environment consists on modifying build.sbt file by adding following line:

javaOptions in Test ++= Seq( "-Dconfig.file=conf/test.conf" )

This entry means that every time when the application starts on test mode, -Dconfig.File=conf/test.conf options is added automatically. The content of our test environment will include all options from application.conf thanks to include "application.conf" call. Only one option, the name of database, will be different for our test environment. The whole test.conf file looks like:

include "application.conf"

db.default.url="mysql://root:root@localhost/play_store_test"

Now we can run our tests from Activator and check if new configuration is taken in consideration. We should see following errors:

[error] Test controllers.UserControllerTest.dashboardConnection failed: java.lang.RuntimeException: Configuration error: Configuration error[Cannot connect to database [default]], took 0.17 sec
// ...
[error] Caused by: Configuration error: Configuration error[Cannot connect to database [default]]
[error]     at play.api.Configuration$.play$api$Configuration$$configError(Configuration.scala:94)
[error]     at play.api.Configuration.reportError(Configuration.scala:743)
// ...
[error] Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown database 'play_store_test'
[error]     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[error]     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
[error]     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
[error]     at java.lang.reflect.Constructor.newInstance(Constructor.java:526)

As you can see, the test.conf is read and db.default.url overrides the same entry from included application.conf file. Now, to solve the "Configuration error" exception we need to copy our production database to play_store_test.

# From MySQL, create new database
mysql> CREATE DATABASE play_store_test;
Query OK, 1 row affected (0.06 sec)

# From command line, export production database and import it to test one
bartosz@bartosz-K70ID:~/workspace/playApp/testApp$ mysqldump -u root  play_store  --password > dumpProd.sql
bartosz@bartosz-K70ID:~/workspace/playApp/testApp$ mysql -u root --password=root -h 127.0.0.1 -D play_store_test  < dumpProd.sql 

This article shows how to prepare our test environment in Play Framework. Firstly, we discovered which commands are useful to execute test cases. We also seen one problematic situation with cache. The second part presented the way of setup different configuration file to test environment.

Share on: