Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » scout » unit test(unit test best practice)
unit test [message #756807] Tue, 15 November 2011 08:38 Go to next message
Bertin Kiekebosch is currently offline Bertin KiekeboschFriend
Messages: 309
Registered: August 2011
Senior Member
Hi,

is there some best practice on how to add unit tests to my Scout project.

regards Bertin.
Re: unit test [message #756883 is a reply to message #756807] Tue, 15 November 2011 12:37 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie BressonFriend
Messages: 796
Registered: October 2011
Senior Member
Yes there are best practices... given by Eclipse (it does not differ from any other RCP application or any other Eclipse Plugins). I am not sure we have documentation, example or tutorial yet.

If you write simple unit test, there will be no problem. The difficulty is when you want to use objects that require the whole OSGi Infrastructure.

Eclipse Scout provides some plug-ins that adds some support to write Tests. Theses plug-ins offers Utilities, Mocks, Assert functions, JUnit Runners in order to ease writing of tests.

  • org.eclipse.scout.rt.testing.client
  • org.eclipse.scout.rt.testing.shared
  • org.eclipse.scout.rt.testing.server
  • org.eclipse.scout.rt.testing.swing
  • org.eclipse.scout.rt.testing.swt


Your test plug-in <your_application>.client.test should have a dependency on org.eclipse.scout.rt.testing.client and so on...

I am also not sure of the state of these testing plug-ins provided with the Indigo -SR1 release of Eclipse Scout.
Re: unit test [message #757087 is a reply to message #756883] Wed, 16 November 2011 12:58 Go to previous messageGo to next message
Andi Bur is currently offline Andi BurFriend
Messages: 4
Registered: March 2010
Junior Member
Scout 3.7-SR1 contains the latest improvements of Scout testing.

At BSI, we create a test fragment for each application plug-in. The fragments contain the very same package structure as their host bundles. This makes it clear where to add a new test for a particular application class. Using fragments also allows accessing package private members of the class under test.

JUnit tests not requiring a running OSGi environment are straight forward. Those dealing with Scout objects (e.g. services, forms, outlines and desktop) have to run within a valid Scout context. Tests executed with a ScoutClientTestRunner or a ScoutServerTestRunner are running within such a context. Both runners can be configured with the @ClientTest and @ServerTest annotations, respectively.

Example:
@RunWith(ScoutClientTestRunner.class)
public class ExampleFormTest {

  private ExampleForm m_form;

  @Before
  public void startUpForm() throws Exception {
    m_form = new ExampleForm();
  }

  @After
  public void closeForm() throws Exception {
    if (m_form != null) {
      m_form.doReset();
      m_form.doCancel();
    }
    m_form = null;
  }

  @Test
  public void testInit() throws Exception {
    m_form.startNew();
    assertEquals("content of UserField is not the current user", 
		ClientSession.get().getUserNr(), m_form.getUserField().getValue());
  }  
}


The test must be executed in a running OSGi environment. Unfortunately Eclipse's JUnit Plug-in test launcher does not work for Scout applications because all target platform and workspace Plug-ins are available in the test environment. A typical Scout application however runs in two different processes, one with all server resources and the other with all client bundles. Having all bundles available in one process would mix up services and service proxies. Therefore two additional product configurations are required.

The additional product configurations should be added to additional test plug-ins. First because Eclipse cannot cope with product extensions in fragment .xml files and second, because there is also an application required that drives the JUnit test execution. Scout provides a default application for this purpose, the ScoutJUnitPluginTestApplication. It is however very likely that there is additional setup required (e.g. registering mock services, authentication, default user...).

This is an extended example test application for scout clients:
public class ExampleClientTestApplication implements IApplication {

  @Override
  public Object start(IApplicationContext context) throws Exception {
    intallNetAuthenticator();
    installCookieStore();
    ScoutClientTestRunner.setDefaultClientSessionClass(ClientSession.class);
    return new ScoutJUnitPluginTestExecutor().runAllTests();
  }

  /**
   * Installs an authenticator that is aware of different client sessions connecting concurrently to the same URL. The
   * authenticator is registered as an OSGi service and used by Scout's network support which is based on Eclipse's
   * networking features.
   * 
   * @return Returns the authenticator's OSGi service registration.
   */
  private Object intallNetAuthenticator() {
    BundleContext bundleContext = Activator.getDefault().getBundle().getBundleContext();
    ServiceRegistration reg = null;
    Hashtable<String, Object> map = new Hashtable<String, Object>();
    map.put(Constants.SERVICE_RANKING, 1);

    // add credentials of test users
    MultiClientAuthenticator.addUser("admin", "admin");
    MultiClientAuthenticator.addUser("standard", "standard");

    MultiClientAuthenticator.setDefaultUser("admin");

    reg = bundleContext.registerService(java.net.Authenticator.class.getName(), new MultiClientAuthenticator(), map);

    // start the netBundle, it is not started from OSGI because no references exists
    Bundle netBundle = Platform.getBundle("org.eclipse.scout.net");
    if (netBundle != null) {
      try {
        netBundle.start();
      }
      catch (Throwable t) {
        netBundle = null;
      }
    }
    return reg;
  }

  /**
   * Installs a cookie store that is aware of different client sessions connecting concurrently to the same URL.
   */
  private void installCookieStore() {
    CookieManager.setDefault(new CookieManager(new MultiClientSessionCookieStore(), CookiePolicy.ACCEPT_ALL));
  }

  @Override
  public void stop() {
  }
}


And the corresponding test application for the server part:
public class BsiCrmServerTestApplication implements IApplication {
  private static final String PERFORM_TESTS_AND_EXIT_ARG_NAME = "performTestsAndExit";

  @Override
  public Object start(IApplicationContext context) throws Exception {
    // add here additional initialization
    if (isExecuteServerSideTests()) {
      ScoutServerTestRunner.setDefaultServerSessionClass(ServerSession.class);
      ScoutServerTestRunner.setDefaultPrincipalName("admin");
      new JUnitServerJob().schedule();
    }
    return IApplication.EXIT_OK;
  }

  @Override
  public void stop() {
  }

  private boolean isExecuteServerSideTests() {
    return TypeCastUtility.castValue(getConfigParameter(PERFORM_TESTS_AND_EXIT_ARG_NAME), boolean.class);
  }

  /**
   * Returns the configuration value for the given parameter that is either configured as
   * command line argument or as system property.
   * 
   * @param parameterName
   * @return
   */
  private String getConfigParameter(String parameterName) {
    String commandLineArgumentName = "-" + parameterName + "=";
    for (String arg : Platform.getCommandLineArgs()) {
      if (arg != null && arg.startsWith(commandLineArgumentName)) {
        return arg.substring(commandLineArgumentName.length());
      }
    }
    return System.getProperty(parameterName);
  }
}


Starting the server product with the command line switch -performTestsAndExit=true executes all tests and stops the server afterwards; setting it to false starts the server so that it could be used by the client test product. Of course, it would be nice to test the client part without starting its server at all. This can be achieved by mocking all server service calls. Scout's testing support provides two methods in the TestingUtility for dynamically registering and unregistering services:

@BeforeClass 
public static void beforeClass() throws Exception { 
  MockService service = new MockService();
  dynamicServices=TestingUtility.registerServices(Activator.getDefault().getBundle().getBundleContext(), 1000, service); 
} 

@AfterClass 
public static void afterClass() throws Exception { 
  TestingUtility.unregisterServices(dynamicServices); 
}


We will provide a more extensive documentation in the wiki.

cheers
Andi
Re: unit test [message #757616 is a reply to message #757087] Sun, 20 November 2011 13:12 Go to previous messageGo to next message
Bertin Kiekebosch is currently offline Bertin KiekeboschFriend
Messages: 309
Registered: August 2011
Senior Member
Thanks a lot,

that is an extensive answer. It will take some time to digest.

Regards Bertin
Re: unit test [message #820486 is a reply to message #757087] Wed, 14 March 2012 07:26 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie BressonFriend
Messages: 796
Registered: October 2011
Senior Member
Hi,

I am trying to set up the test fragment...
In intallNetAuthenticator() you call Constants.SERVICE_RANKING.

What is this Constants Class and what is the Value?

Configuration: Swing Application and Jan2012 Branch.

.
Re: unit test [message #820667 is a reply to message #820486] Wed, 14 March 2012 12:11 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie BressonFriend
Messages: 796
Registered: October 2011
Senior Member
J. Br. wrote on Wed, 14 March 2012 08:26
In intallNetAuthenticator() you call Constants.SERVICE_RANKING.

What is this Constants Class and what is the Value?


org.osgi.framework.Constants:

public static final String SERVICE_RANKING = "service.ranking";
Re: unit test [message #831395 is a reply to message #756883] Wed, 28 March 2012 21:17 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie BressonFriend
Messages: 118
Registered: November 2010
Senior Member
J. Br. wrote on Tue, 15 November 2011 13:37

  • org.eclipse.scout.rt.testing.client
  • org.eclipse.scout.rt.testing.shared
  • org.eclipse.scout.rt.testing.server
  • org.eclipse.scout.rt.testing.swing
  • org.eclipse.scout.rt.testing.swt


What is the official location to get these plugins? Is there any p2 updatesite, features, repository to get them?
Re: unit test [message #840522 is a reply to message #831395] Tue, 10 April 2012 07:38 Go to previous messageGo to next message
Judith Gull is currently offline Judith GullFriend
Messages: 54
Registered: February 2010
Member
There is currently no p2 updatesite available. You can checkout and export the plugins.

We should create a new testing feature and add it to our updatesite.
Re: unit test [message #841014 is a reply to message #840522] Tue, 10 April 2012 20:04 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie BressonFriend
Messages: 118
Registered: November 2010
Senior Member
Judith Gull wrote on Tue, 10 April 2012 09:38
We should create a new testing feature and add it to our updatesite.


Should I open a Bugzilla ticket?
Re: unit test [message #841356 is a reply to message #840522] Wed, 11 April 2012 07:40 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie BressonFriend
Messages: 796
Registered: October 2011
Senior Member
Judith Gull wrote on Tue, 10 April 2012 09:38
We should create a new testing feature and add it to our updatesite.

See Bugzilla 376459.
Re: unit test [message #841380 is a reply to message #841356] Wed, 11 April 2012 08:23 Go to previous message
Claudio Guglielmo is currently offline Claudio GuglielmoFriend
Messages: 128
Registered: March 2010
Senior Member
Thank you Jérémie for opening the bug.
Previous Topic:AccessControlService and Permission cache
Next Topic:Juno: %trimmedwindow.label.eclipseSDK in the main window.
Goto Forum:
  


Current Time: Wed Nov 26 19:07:26 GMT 2014

Powered by FUDForum. Page generated in 0.02250 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software