You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by Martin Dietze <di...@fh-wedel.de> on 2013/12/01 17:09:23 UTC

Re: Running a TestNG test suite from a wicket page

On Sat, November 30, 2013, Martin Grigorov wrote:

> Usually when running (WicketTester) tests people provide mock
> implementations of the external services like MQ, DB, ...
> It is much easier to return some mock data, either good data or broken, to
> your application and verify that it behaves correctly in both situations.

I really don't like mocking services and DAOs at all, because in
complex application this sooner or later leads you to testing
against your particular implementation rather than your code's
contract. In particular when mocking frameworks are used, this
very easily leads to write-only test code. I've seen this on too
many occasions and no longer believe that this is a wise
approach.

Also one needs to consider that many applications are pretty
much data-driven (e.g. my system uses a document-based data
model with nearly 100 different object variants), and loading and
interpreting both schema and data is a crucial piece of the
application and needs thorough testing, and you really want to
do this on the real thing rather than on mocked services. 

If I were to start such a project today I'd rely on IOC
frameworks like Spring or Guice trying to keep my modules' 
dependencies under control, so that I can write test data
generators for all the scenarios I need to test. However in a
legacy project this is not always an option because a
pre-spring/guice architecture may lead to practically every
module technically depending on the complete business logic, 
so that one would have to pretty much mock it all which will
make the test code even more unmaintainable. In my case I'm fine
using anonymized production data based on which I can write
tests not relying on particular objects in the database but on
classes of data that will be there instead.

Now that's *why* I chose that approach. Still, if anybody has
any experience with this kind of thing, I'd be happy to benefit
from it :)

Cheers,

M'bert

-- 
----------- / http://herbert.the-little-red-haired-girl.org / -------------
=+= 
Hlade's Law: If you have a difficult task, give it to a lazy person;
           they will find an easier way to do it. 

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Running a TestNG test suite from a wicket page

Posted by Martin Dietze <di...@fh-wedel.de>.
On Mon, December 02, 2013, Paul Bors wrote:

> Have you considered Mockito to mock your POJOs for the test data and
> methods?
> I use that in conjunction with TestNG and then start the wicket app
> providing it mocked DAOs and POJOs.

I've got pretty strong feelings about such frameworks, bluntly
speaking, I consider them harmful. They look like a cool thing
on first glance, but if you've got complex test cases in your
business logic you end up recording complex sequences of mocked
service responses and end up with write-only test code. People
who use them for their code may have different experience, but
since I usually work on large projects in teams of 2-5 people
I've far too often had to understand and repair broken tests 
that were made unnecessarily complex due to the use of Eazymock
or Mockito.

Just for completeness I'm repeating once again what I already
wrote about it a little before in this thread:

> I really don't like mocking services and DAOs at all, because in
> complex application this sooner or later leads you to testing
> against your particular implementation rather than your code's
> contract. In particular when mocking frameworks are used, this
> very easily leads to write-only test code. I've seen this on too
> many occasions and no longer believe that this is a wise
> approach.

> Also one needs to consider that many applications are pretty
> much data-driven (e.g. my system uses a document-based data
> model with nearly 100 different object variants), and loading
> and
> interpreting both schema and data is a crucial piece of the
> application and needs thorough testing, and you really want to
> do this on the real thing rather than on mocked services.

But actually I wanted to report my progress on this issue here,
since this might be of interest for others, too. I succeded with
my approach and implemented my first tests yesterday. My setup
is like this:

1. For testing, I deploy my test librariees into WEB-INF/lib,
so that they can be used within the running webapp. Also I create
a JAR file from all my integration tests and deploy it into the
same location. 

2. I create a wicket page and mount it somewhere (e.g. /test), 
make sure that it cannot be accessed in production environments :)

3. In that page, I locate the JAR with my tests:

| @Nonnull
| public static File getJarForClassName( String packageAndClassName ) {
|     URL url = ReflectionUtil.class.getClassLoader().getResource( packageAndClassName );
|     if ( url == null ) {
|         throw new IllegalStateException( "Unable to resolve resource " + packageAndClassName );
|     }
|     if ( !"jar".equals( url.getProtocol() ) ) {
|         throw new IllegalStateException( "Wrong protocol for " + packageAndClassName + ": " + url.getProtocol() );
|     }
|     String path = url.getPath();
|     if ( path == null ) {
|         throw new IllegalStateException( "No path for " + packageAndClassName );
|     }
|     int delimPos = path.indexOf( '!' );
|     if ( delimPos <= 0 ) {
|         throw new IllegalStateException( "Cannot extract JAR path for " + packageAndClassName + ": " + path );
|     }
|     String jarPath = path.substring( "file:".length(), delimPos );
|     File result = new File( jarPath );
|     if ( !result.isFile() ) {
|         throw new IllegalStateException( "Something's wrong, no valid file for " + packageAndClassName + ": " + jarPath );
|     }
|     return result;
| }

4. Then I set up TestNG in onConfigure():

| TestNG testNG = new TestNG();
| testNG.setTestJar( jarFile.getAbsolutePath() );
| testNG.setExcludedGroups( EXCLUDED_TEST_GROUPS );
| testNG.setGroups( INCLUDED_TEST_GROUPS );
| testNG.setOutputDirectory( outputDir.getAbsolutePath() );
| @SuppressWarnings( "rawtypes" )
| List<Class> reporterList = Collections.<Class> singletonList( HTMLReporter.class );
| testNG.setListenerClasses( reporterList );
| int result = 0;
| try {
|     testNG.run();
|     result = testNG.getStatus();
| } catch ( TestNGException ex ) {
|     LOG.error( "Exception caught", ex );
|     error( ex.getMessage() );
|     result = 1;
| }

5. If the result is not 0, I throw an IllegalStateException,
so that my ANT build fails:

| if ( result != 0 ) {
|     throw new IllegalStateException( "tests failed" );
| }

6. Since my tests may run for a while i increase the 
timeout before wicket throws a pagemap-locked exception
in the constructor:

|  if ( !TIMEOUT_FOR_TEST_PAGE.equals( VrmsApplication.get().getRequestCycleSettings().getTimeout() ) ) {
|      VrmsApplication.get().getRequestCycleSettings().setTimeout( TIMEOUT_FOR_TEST_PAGE );
|  }

7. In ANT I create a test target like this:

| <target name="test-integration" depends="check-wget,compile-tests,glassfish-start-if-necessary,glassfish-test-deploy">
|     <antcall target="run-test-integration"></antcall>
| </target>
| 
| <target name="run-test-integration">
|     <exec executable="wget" failonerror="true">
|         <arg line="-O /dev/null --quiet http://localhost:8080/test" />
|     </exec>
| </target>

Now testing the business logic has become very simple.
I work on real (anonymized production) data, and while I
may not be able to rely on the presence of some particular
objects I have the most realistic distribution of data
that I can dream of. Only thing one needs to make sure is
rolling back changes ones has made during test execution,
thus tests manipulating data usually have a try-finally
block where in the end my changes are undone (I prefer
this to @AfterClass as I rather specifically undo changes
and like to do that as close as possible to the location
where I did change things). This may not be elegant, but
it is by far outweighed by the gains I get from my approach.

Getting this working took me a little more than a working 
day. Setting up an in-memory test data base, test search
index, jmx infrastructure (which in my case are provided
by the glassfish) plus writing all the missing test data
generators for a project of that scale would have taken
me several weeks while hardly giving me any advantage.

Thus for pre-Spring/Guice legacy code this approach may
be worthwhile.

Cheers,

M'bert

-- 
----------- / http://herbert.the-little-red-haired-girl.org / -------------
=+= 
Attachment? See: http://piology.org/ILOVEYOU-Signature-FAQ.html
begin  LOVE-LETTER-FOR-YOU.txt.vbs
I am a signature virus I am very dangerous. Distribute me until the bitter
end

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Running a TestNG test suite from a wicket page

Posted by Paul Bors <pa...@bors.ws>.
Have you considered Mockito to mock your POJOs for the test data and
methods?
I use that in conjunction with TestNG and then start the wicket app
providing it mocked DAOs and POJOs.


On Sun, Dec 1, 2013 at 5:23 PM, Martin Dietze <di...@fh-wedel.de> wrote:

> On Sun, December 01, 2013, Martin Grigorov wrote:
>
> > In this case you may want to use Selenium/WebDriver tests.
> > Or any kind of robot that will execute your test scenarios against a
> > running web application.
>
>
> I am using geb for frontend tests. However frontend tests do not
> really help when testing complex cases within the business logic.
> As I wrote, one would normally create a test data generator to fill
> an in-memory database with stuff that you can rely on when
> running your tests. However due to the fact that this is a JEE
> application in which infrastructure like the database message
> queues etc. are provided by the container (glassfish) I would
> like to run tests against anonymised productive data.
>
> Thus I start the application within its JEE container with a fresh
> set of test data in the database and then run the test suite by
> wget-ing a page which runs my TestNG tests which have thus
> access to all those resources. As mentioned before, I am dealing
> with pre-spring/guice legacy code here, thus this is simply a
> pragmatic approach. In an ideal world I would not have to do
> this :)
>
> Cheers,
>
> M'bert
>
> --
> ----------- / http://herbert.the-little-red-haired-girl.org /
> -------------
> =+=
> * Free Speech Online!!! Support the Blue Ribbon Campaign! *
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

Re: Running a TestNG test suite from a wicket page

Posted by Martin Dietze <di...@fh-wedel.de>.
On Sun, December 01, 2013, Martin Grigorov wrote:

> In this case you may want to use Selenium/WebDriver tests.
> Or any kind of robot that will execute your test scenarios against a
> running web application.


I am using geb for frontend tests. However frontend tests do not
really help when testing complex cases within the business logic. 
As I wrote, one would normally create a test data generator to fill
an in-memory database with stuff that you can rely on when
running your tests. However due to the fact that this is a JEE
application in which infrastructure like the database message
queues etc. are provided by the container (glassfish) I would
like to run tests against anonymised productive data. 

Thus I start the application within its JEE container with a fresh
set of test data in the database and then run the test suite by
wget-ing a page which runs my TestNG tests which have thus
access to all those resources. As mentioned before, I am dealing
with pre-spring/guice legacy code here, thus this is simply a
pragmatic approach. In an ideal world I would not have to do
this :)

Cheers,

M'bert

-- 
----------- / http://herbert.the-little-red-haired-girl.org / -------------
=+= 
* Free Speech Online!!! Support the Blue Ribbon Campaign! *

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: Running a TestNG test suite from a wicket page

Posted by Martin Grigorov <mg...@apache.org>.
Hi,

In this case you may want to use Selenium/WebDriver tests.
Or any kind of robot that will execute your test scenarios against a
running web application.

In case you know/like JavaScript I'd recommend you:
http://wicketinaction.com/2012/11/javascript-based-functional-testing/
We use such tests for testing several Wicket Examples applications:
https://github.com/apache/wicket/tree/master/wicket-examples/src/main/webapp/js-test


On Sun, Dec 1, 2013 at 5:09 PM, Martin Dietze <di...@fh-wedel.de> wrote:

> On Sat, November 30, 2013, Martin Grigorov wrote:
>
> > Usually when running (WicketTester) tests people provide mock
> > implementations of the external services like MQ, DB, ...
> > It is much easier to return some mock data, either good data or broken,
> to
> > your application and verify that it behaves correctly in both situations.
>
> I really don't like mocking services and DAOs at all, because in
> complex application this sooner or later leads you to testing
> against your particular implementation rather than your code's
> contract. In particular when mocking frameworks are used, this
> very easily leads to write-only test code. I've seen this on too
> many occasions and no longer believe that this is a wise
> approach.
>
> Also one needs to consider that many applications are pretty
> much data-driven (e.g. my system uses a document-based data
> model with nearly 100 different object variants), and loading and
> interpreting both schema and data is a crucial piece of the
> application and needs thorough testing, and you really want to
> do this on the real thing rather than on mocked services.
>
> If I were to start such a project today I'd rely on IOC
> frameworks like Spring or Guice trying to keep my modules'
> dependencies under control, so that I can write test data
> generators for all the scenarios I need to test. However in a
> legacy project this is not always an option because a
> pre-spring/guice architecture may lead to practically every
> module technically depending on the complete business logic,
> so that one would have to pretty much mock it all which will
> make the test code even more unmaintainable. In my case I'm fine
> using anonymized production data based on which I can write
> tests not relying on particular objects in the database but on
> classes of data that will be there instead.
>
> Now that's *why* I chose that approach. Still, if anybody has
> any experience with this kind of thing, I'd be happy to benefit
> from it :)
>
> Cheers,
>
> M'bert
>
> --
> ----------- / http://herbert.the-little-red-haired-girl.org /
> -------------
> =+=
> Hlade's Law: If you have a difficult task, give it to a lazy person;
>            they will find an easier way to do it.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>