WARNING:This tutorial is being written! Do not hesitate to report any errors or suggestions..
Quick access:
Some reminders about JUnit
Implementation of a test of a web page
JUnit is a library that allows you to make packages of tests on Java code. As its name suggests, it allows to implement unit tests on your classes, but it also allows to make functional tests of integration, or technical tests of integration. The JUnit library is available from the following address: http://www.junit.org.
We can say that there are two main versions of JUnit: JUnit 3 (or older) and JUnit 4 (and later). The fundamental difference
between these two versions is related to the contributions of Java SE 5.0. Indeed, before this version of Java, JUnit was based on a model
of inheritance (junit.framework.TestCase) and on coding conventions (the names of the test methods should be prefixed by the four
letters test).
Since JUnit 4, these rules have been abandoned and instead, the use of Java annotations is recommended (and in particular, the annotation
org.junit.Test). This makes it possible to choose a mother class (in terms of inheritance), unlike the first technique
which requires the class junit.framework.TestCase.
Finally, don't remember that JUnit is integrated into the main IDE
Java (NetBeans and
Eclipse in particular). In the case of Eclipse, you simply have to click with the right mouse button on the file containing the test class,
or on a package containing this file and to ask "Run As / JUnit Test". The "JUnit" view should display the results of your
test campaign. For example here is a screenshot of the Eclipse IDE showing the integration of JUnit (for information, the tests shown in
this screenshot correspond to a part of the tests of non-regression of the Ellipse framework: These tests are checked every time before an online
of a new version of the framework). Also note that errors have been deliberately produced to show you a case of failure of tests execution.
To implement a set of test on an Ellipse web page, we will once again, rely on
the demonstration application of the Ellipse framework. This Ellipse project contains a directory containing two
tests for our webpage of authentication (Login.wp). The test directory is accessible from "WEB-INF/tests".
For example, here is the code to be tested: this is the class "corelib.services.web.samples.virtualcaddy.webpages.Login" that allows to
accept or reject the connection of a user. Note that if the connection is accepted, we are returned to the page
"SelectArticle.wp" and the session is updated. Otherwise, there is no redirection and the session remains unchanged.
01 package corelib.services.web.samples.virtualcaddy.webpages;
02
03 import corelib.services.web.components.Button;
04 import corelib.services.web.components.OutputText;
05 import corelib.services.web.components.TextBox;
06 import corelib.services.web.components.events.ActionEvent;
07 import corelib.services.web.components.events.ActionListener;
08 import corelib.services.web.samples.virtualcaddy.business.User;
09 import corelib.services.web.samples.virtualcaddy.business.UserHome;
10 import corelib.services.web.webapplications.WebPage;
11 import corelib.services.web.webapplications.events.WebPageEvent;
12
13 public class Login extends WebPage {
14
15 private TextBox txtLogin = null;
16 private TextBox txtPassword = null;
17 private Button btnConnect = null;
18 private OutputText lblResult = null;
19
20
21 public void page_load( WebPageEvent webPageEvent ) {
22 this.traceLogger.info( "Virtual Caddy", "page_load" );
23 this.btnConnect.addActionListener( new ActionListener() {
24 public void actionPerformed( ActionEvent event ) {
25 btnConnect_actionPerformed( event );
26 }
27 });
28 }
29
30 public void btnConnect_actionPerformed( ActionEvent event ) {
31 String login = txtLogin.getValue();
32 String password = txtPassword.getValue();
33
34 User user = UserHome.findByConnectInformations( login, password );
35 if ( user != null ) {
36 this.session.setAttribute( "user", user );
37 this.redirect( "SelectArticle.wp" );
38 } else {
39 lblResult.setText( "Bad connection for user : " + login );
40 this.traceLogger.warning( "Virtual Caddy", "Bad connection" );
41 this.traceLogger.error( "Virtual Caddy", "Bad connection" );
42 }
43 }
44 }Now we must write at least two classes of tests to verify a successful submission of the page (login/password is correct) and a failure submission of the page (login/password is not recognized). It is important to test the failures: we must check that if such a situation happens, your code will behave correctly. I even want to say that it is more important to test all cases of failure known. Here is the code of the first test.
01 package corelib.services.web.samples.virtualcaddy.webpages;
02
03 import org.junit.Assert;
04 import org.junit.Test;
05
06 import corelib.services.web.samples.virtualcaddy.business.User;
07 import corelib.services.web.tests.WebPageLoaderForTesting;
08
09 public class LoginTestsSuccess extends WebPageLoaderForTesting<Login> {
10
11 public LoginTestsSuccess() throws Exception {
12 super( "Login.wp", "POST" );
13 this.request.setParameter( "txtLogin", "Malone" );
14 this.request.setParameter( "txtPassword", "P@ssw0rd" );
15 this.request.setParameter( "btnConnect", "" );
16 this.start();
17 }
18
19 @Test public void testReturns() {
20 Assert.assertEquals( response.getStatus(), 200 );
21 Assert.assertEquals( response.getRedirectionURL(), "SelectArticle.wp" );
22 User user = (User)this.request.getSession().getAttribute( "user" );
23 if ( user instanceof User == false ) Assert.fail();
24 }
25
26 }
If we can do such tests, this is because the Java EE platform and the Ellipse framework attach the web components and the HTTP server by
using Java interfaces. Thus, instead of showing a real HTTP server to our test class, we provide it a set of implementations of these
interfaces that allow to simulate the behavior of an HTTP server. We talk about the mock objects. You can find the
implementations of these mock objects in the following classes: corelib.services.web.tests.MockedHttpRequest,
corelib.services.web.tests.MockedHttpResponse, corelib.services.web.tests.MockedHttpSession,
corelib.services.web.tests.MockedHttpServlet and corelib.services.web.tests.MockedServletContext.
In line 20 we check the HTTP state returned. Only two values can be returned: 200 if all goes well or 500 if an internal processing error
on the page was dectected. In line 21, we check if a redirect on the page "SelectArticle.wp" has been well requested. Then on
line 22, we check that the session has been well modified as expected.
Warning: it is also important that your web components are coupled with your business objects by interface to support (in the same extent) the tests for your web pages. Clearly this is not what is presented in this example (which was intended to be the most simplistic possible).
The sample code below shows a test example of the web page for a login/password not allowed. Its code is quite similar with the previous example.
01 package corelib.services.web.samples.virtualcaddy.webpages;
02
03 import org.junit.Assert;
04 import org.junit.Test;
05
06 import corelib.services.web.samples.virtualcaddy.business.User;
07 import corelib.services.web.tests.WebPageLoaderForTesting;
08
09 public class LoginTestsFailure extends WebPageLoaderForTesting<Login> {
10
11 public LoginTestsFailure() throws Exception {
12 super( "Login.wp", "POST" );
13 this.request.setParameter( "txtLogin", "Toto" );
14 this.request.setParameter( "txtPassword", "Titi" );
15 this.request.setParameter( "btnConnect", "" );
16 this.start();
17 }
18
19 @Test public void testReturns() {
20 Assert.assertEquals( response.getStatus(), 200 );
21 Assert.assertEquals( response.getRedirectionURL(), null );
22 User user = (User)this.request.getSession().getAttribute( "user" );
23 if ( user != null ) Assert.fail();
24 }
25
26 }
|
|
|||||||