Test your application

Creating automatic test suites for your application is a good way to make it robust. It allows you to work in a very agile way.

Play tests are built using JUnit 4 or Selenium depending what you want to test.

Writing tests

The tests must be created in the test/ directory. This folder will only be added to the sources path when the application is run in test mode. You can write 3 different kinds of tests.

Unit test

A unit test is written using JUnit. In this kind of test you can test the model of your application (including some utilities).

Here is an example of a Unit test:

import play.test.*;
import org.junit.*;

public class MyTest extends UnitTest {

    @Test
    public void aTest() {
        assertEquals(2, 1 + 1); // A really important thing to test
    }

    @Test
    public void testUsers() {
        assertEquals(3, Users.count());
    }

}

Functional test

A functional test is written using JUnit. In this kind of test you can test your application by accessing directly the controller objects.

Here is an example of a Functional test:

import play.test.*;
import play.mvc.*;
import play.mvc.Http.*;
import org.junit.*;

public class ApplicationTest extends FunctionalTest {

    @Test
    public void testTheHomePage() {
        Response response = GET("/");
        assertStatus(200, response);
    }

}

Selenium test

Acceptance tests are written using Selenium. Here you can test your application by running it in an automated browser.

Selenium tests are written using HTML tables. You can either use this native syntax or use the #{selenium /} tag.

Here is an example of a Selenium test:

#{selenium ‘Test security‘}

    // Try to log in the administration area
    clearSession()
    open(‘/admin‘)
    assertTextPresent(‘Login‘)
    type(‘login‘, ‘admin‘)
    type(‘password‘, ‘secret‘)
    clickAndWait(‘signin‘)

    // Verify that the user in correctly logged in
    assertText(‘success‘, ‘Welcom admin!‘)

#{/selenium}

Because Selenium tests are run within your browser access to emails sent by the mock email and to String values placed in the Play Cache must be made using extensions to Selenium.

Here is an example of accessing the most recent email sent to a specific email account:

#{selenium ‘Test email sending‘}

    // Open email form and send an email to [email protected]
    open(‘/sendEmail‘)
    assertTextPresent(‘Email form‘)
    type(‘To‘, ‘[email protected]‘)
    type(‘Subject‘, ‘Berillium Subject‘)
    clickAndWait(‘send‘)

	// Extract the last email sent to [email protected] into a javascript variable called email
	storeLastReceivedEmailBy(‘[email protected]‘, ‘email‘)
	// Extract the subject line from the email variable into a variable called subject
	store(‘javascript{/Subject:\s+(.*)/.exec(storedVars["email"])[1]}‘, ‘subject‘)
	// Test the contents of the subject variable
	assertEquals(‘Berillium Subject‘, ‘$[subject]‘)

#{/selenium}

Here is an example of accessing a String stored in the Play Cache (for example the correct answer to a CAPTCHA):

#{selenium ‘Get string from cache‘}

	open(‘/register‘)
	assertTextPresent(‘Registration form‘)
	type(‘Email‘, ‘[email protected]‘)
	type(‘Password‘, ‘secretpass‘)
	type(‘Password2‘, ‘secretpass‘)
	// .. Fill in the registration form ..

// Get the value of the magicKey variable from the cache (set to the CAPTCHA answer in the application)
storeCacheEntry(‘magicKey’, ‘captchaAnswer’)
// Type it into the form
type(‘Answer’, ‘$[captchaAnswer]’)

clickAndWait(‘register’)

#{/selenium}

Fixtures

When you run tests, you need to have stable data for your application. The simplest way is to reset your database before each test.

The play.test.Fixtures class helps you to manipulate your database and to inject test data. You typically use it in a @Before method of a JUnit test.

@Before
public void setUp() {
    Fixtures.deleteAll();
}

To import data, it is simpler to define them in a YAML file that the Fixtures helper can automatically import.

# Test data

Company(google):
   name:    Google

Company(zen):
   name:    Zenexity

User(guillaume):
   name:    guillaume
   company: zen

And then:

@Before
public void setUp() {
    Fixtures.deleteAll();
    Fixtures.loadModels("data.yml");
}

You can read more about Play and YAML in the YAML manual page.

For Selenium tests, you can use the #{fixture /} tag:

#{fixture delete:‘all‘, load:‘data.yml‘ /}

#{selenium}

    // Write your test here

#{/selenium}

Sometimes it is convenient to split data into several YAML files. You can load fixtures from multiple files at once:

Fixtures.loadModels("users.yml", "roles.yml", "permissions.yml");

and for Selenium tests:

#{fixture delete:‘all‘, load:[‘users.yml‘, ‘roles.yml‘, ‘permissions.yml‘] /}

Running the tests

To run the tests, you must run your application in test mode using the play test command.

# play test myApp

In this mode, Play will automatically load the test-runner module. This module provides a Web based test runner, available at the http://localhost:9000/@tests URL.

When you run a test, the result is saved into the /test-result directory of your application.

On the test runner page, each test is a link. You can ‘right click’ and ‘Open in a new tab’, to run the test directly outside of the test-runner.

When you run tests this way, Play will start with a special test framework ID. So you can define special configurations in the application.conf file.

If you want several different test-configuration, you can use framework IDs matching the pattern ‘test-?.*’ (e.g: ‘test-special’).
If you use a framework ID other then the default ‘test’, you must make sure ALL test configuration in application.conf is available
with that framework ID. When launching test with special test framework ID you do it like this: ‘play test --%test-your-special-id‘

For example:

%test.db=mem
%test.jpa.ddl=create-drop

Continuous integration, and running the tests automatically

The auto-test command does the same as the test command, but it automatically launches a browser, runs all the tests, and stops.

This is a useful command if you want to set up a continuous integration system;

After the run, all results are saved to the /test-result directory. Moreover, this directory contains a marker file (either result.failed or result.passed) for the test suite’s final result. Finally, this directory contains all the logs, in an application.log file.

So setting up a continuous integration system to test your application, could be:

  • Checkout the latest version of your application
  • Run play auto-test
  • Wait for the end of the process
  • Check for the marker file result.passed or result.failed in the /test-result directory

Run these steps in a CRON tab, and you’re done!

Continuing the discussion

Next: Security guide.

时间: 2024-11-04 23:50:22

Test your application的相关文章

springboot的application.properties与.yml的区别

现在我们的application.properties文件内容是: [plain] view plain copy server.port=8090 server.session-timeout=30 server.context-path= server.tomcat.max-threads=0 server.tomcat.uri-encoding=UTF-8 spring.datasource.url = jdbc:mysql://localhost:3306/newbirds spring

Catch Application Exceptions in a Windows Forms Application

You need to handle the System.Windows.Forms.Application.ThreadException event for Windows Forms. This article really helped me: http://bytes.com/forum/thread236199.html. Application.ThreadException += new ThreadExceptionEventHandler(MyCommonException

android Application Component研究之Activity(一)

http://blog.csdn.net/windskier/article/details/7096521 终于下定决心写写ActivityManagerService的源码分析的文章了,ActivityManagerService 业务的整个逻辑关系被各种复杂的数据结构包裹着,因此对ActivityManagerService 的分析主要就是对各种数据结构的分析,明白了这些数据结构,理解ActivityManagerService的业务内容就水到渠成了. AMS提供了一个ArrayList

web初学之request,session与application

request (1)request的setAttribute()与getAttribute()方法一般都是成对出现,首先通过setAttribute()方法设置属性与属性值,然后通过getAttribute()方法根据属性获取到与该属性对应的对象值.setAttribute()与getAttribute()方法都是在服务器端内部执行,客户端并不清楚.(注意:getAttribute()之后需要进行向下类型转换,将属性值转换为真正的对象) (2)request的getParameter()方法是

devise登陆页不使用application模版

class ApplicationController < ActionController::Base   layout :layout   private   def layout     # only turn it off for login pages:     is_a?(Devise::SessionsController) ? false : "application"     # or turn layout off for every devise contr

Android Application 类共享全局数据

android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例模式的一个类.且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期.因为它是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象.所以通过Application来进行一些,数据传递,数据共享 等,数据缓存等操作,代码如下: package com.example.five; import andro

page request session application 范围

在JSP页面中的对象,包括用户创建的对象(例如,JavaBean对象)和JSP的隐含对象,都有一个范围属性.范围定义了在什么时间内, 在哪一个JSP页面中可以访问这些对象.例如,session对象在会话期间内,可以在多个页面中被访问.application对象在整个Web应 用程序的生命周期中都可以被访问.在JSP中,有4种范围,如下所示. 1. page范围 具有page范围的对象被绑定到javax.servlet.jsp.PageContext对象中.在这个范围内的对象,只能在创建对象的页面

匿名访问之(一)web application级别

如果用SharePoint做一个对外开放的公共站点,比如公司展示网站,那么浏览网站的人不需要注册和登陆,就应该能看到内容.这个时候就需要对站点开启匿名访问. SharePoint的匿名访问是从上而下的,Farm管理员可以在Central Administration里,在Web Application级别做总控. 在Web Application页面,选择一个Web Application,点击ribbon上的Anonymous Policy: 发现这里的设置并没有开启: 这是因为并没有在这个W

IOS Application生命周期

应用程序的状态 Not running(未运行):程序没启动 Inactive(未激活):程序在前台运行,不过没有接收到事件.在没有事件处理情况下程序通常停留在这个状态 Active(激活):程序在前台运行而且接收到了事件.这也是前台的一个正常的模式 Backgroud(后台):序在后台而且能执行代码,大多数程序进入这个后台后会在在这个状态上停留一会.时间到之后会进入挂起状态(Suspended).有的程序经过特殊的请求后可以长期处于Backgroud状态 Suspended(挂起):程序在后台

The web application you are attempting to access on this web server is currently unavailable.......

今天去服务器安装了个.net 4.0 framework(原本有1.0和2.0的),配置好站点后,选择版本为4.0,访问出错,错误代码如下 Server Application Unavailable The web application you are attempting to access on this web server is currently unavailable.  Please hit the "Refresh" button in your web brows