Testing

Prev: Read Content - Next: Edit Content

In this section we will see how to write tests with the framework mocked environment.

Test environment

AgileSites provides a mocking enviroment to easily write unit tests.

Tests actually check the integrity of the java controller logic, content model and html view and they must be run from the integrated test runner that is generated by the site generator.

The test runner is accessible with http://localhost:8080/cs/ContentServer?pagename=mysite-tester

Change the mysite to the lowercase version of your site name.

All the tests run by the tester are listed in app/src/resources/tests.txt

A test class is automatically created when you use the wcs-generate and the class name is added to the list. Then you complete the test adding assertions that are based . Here is a typical test, whose meaning is explained in the following:

public class SummaryTest extends TestElement {
    final static Log log = Log.getLog(SummaryTest.class);
    Summary it;

    @Before
    public void setUp() {
        it = new Summary();
    }

    @Test
    public void testHome() {
        parse(it.apply(env("")));
        //dump(log);
        assertText("h4", "Home");       
        assertTextContains("div div", "Welcome!");
    }

    @Test
    public void testAbout() {
        parse(it.apply(env("")));
        //dump(log);
        assertText("h4", "About");      
        assertTextContains("div div", "About us...");
    }
}

TestElement

Each test will exercise the java code of a template or cselement, implemented mostly as classes derived by theElement base class. The main logic is in the apply method that takes an Env as argument.

Because tests exercise also the business logic applied to the cms, you need to run the tests with the Tester of your web site. Each test should extend the TestElement base class, that is a jUnit4 test case.

Following the standard jUnit4 practices, you have to mark each test method with the @Test annotation, initializations with @Before and cleanup with @After.

In the sample you see that the setUp method will create an instance of the Element class and then execute the tests.

env()

Since the Env is the facade used to access to all the other resources, a test must be run passing an Env to the apply method.

The test element provides an env(String) method to generate a mocked TestEnv. Thre result of the apply methods is special String that is normally rendered by the CMS but the TestElement provides also the the method parse to parse the result in a way that is easy to analyze.

For this reason each test starts with:

parse(it.apply(env("")));

where env("") will generate an enviroment, then it.apply will run the code to be tested and finally parse will prepare the result for analysis.

initialize the mocked env

An important parameter of the env method is the String parameter, that is passed to the router for initializing the enviroment. Check the routing documentation for details.

If you write env("") then the mocked env will be the same as the enviroment generated by the url http://localhost:8080/cs/Satellite/mysite, while the env("/Home") will be the same as if you use the http://localhost:8080/cs/Satellite/mysite/About. Indeed the Router receive always the part of the url that after the prefix /cs/Satellite/mysite.

Because the router usually maps names in url, using "" will initilize c/cid to c=Page and the cid of the Page Home, while the second will initialize the c/cid to the ones of the page About. Default router allows also to specificy /News/Today to set c/cid to the asset of type Demo_News named Today`.

Of course since the router is extensible, this behaviour can be changed. It really depends on the router implementation.

Assertions

Once you have initialized the enviroment, you can finally run some assertions on it. Assertions are based on the same selectors used in the Picker

Available methods are:

  • assertText(selector, text) will test that the text of the html selected by the selector is the same as the text.
  • assertTextContains(selector, text) will test that the text of the html selected by the selector contains the text.
  • assertHtml(selector, htmltext) will test that the inner html (tag included) selected by the selector is the same as the htmltext.
  • assertOuterHtml(selector, htmltext) will test that the outer html (tag included) selected by the selector is the same as the htmltext.
  • assertAttr(selector, attribute, text) will test that the attribute of the tag selected by the selector is the same as the text.
  • assertAttrContains(selector, attribute, text) will test that the attribute of the tag selected by the selector contains the text.

You can use also generic assertions extracting a piece of text with text(selector), an attribute with attr(selector, attribute), selecting a subtree with select(selector) and finally generally apply any JUnit assertions on nodes extracted by the current document, accessible with the doc variable using JSoup methods.

Logger

When you debug a test, it is very helpful to use the logging support. From the shello, the command wcs-log view will show a gui log viewer. This log viewer is socket based. You can start a server from the menu , that will propose by default a socket listening in port 4445. You can actually create multiple log windows listening in different ports. This way you may listen for example the log for the api in a windows and the log for your application in another windows.

You can then enable log at a given level for the package or class you want. For example wcs-log trace mysite will start logging at the trace level all the classes in the package and in subpackage of the package mysite (where usually is your site code).

You can also set anoter port in the log: wcs-log debug wcs 4444 will log at debug level everything in the package and subpackages wcs (that is the package of the AgileSites API - remember to create a window in the log viewer to see the logs).

Last but not least: you can see which logs are enabled with wcs-log list and you can stop a log stream, for example of the package mysite with wcs-log stop mysite.