Testing Java Applications using Groovy blocks/en: Unterschied zwischen den Versionen

Aus expecco Wiki (Version 2.x)
Zur Navigation springen Zur Suche springen
Zeile 229: Zeile 229:


* cleanup ''You'' / ''we''
* cleanup ''You'' / ''we''
* write wrap-up section
* Upload standalone .ets and .zip with Eclipse project Java doc somewhere
* Upload standalone .ets and .zip with Eclipse project Java doc somewhere
* Upload Java doc somewhere
* Upload Java doc somewhere

Version vom 3. Oktober 2014, 11:53 Uhr

This example demonstrates how to use Java Browser/en, Java Debugger/en and SmallSense/en plugins for Java application test development. It shows how to use Groovy blocks to

The Bank Account Example[Bearbeiten]

Through this tutorial, we'll use a simple "Bank Account" as system under test. "Bank Account" is a very simple Java library that models banks and accounts and allow transation among accounts.

The code of the "Bank Account" application is not correct at place bu purpose. You may download a full Eclipse project containing the example code at somewhere.

Setting up expecco[Bearbeiten]

For the sake of brevity, in this tutorial we'll use simple local JVM managed by expecco to run "Bank Account"s code. As for any Java application, we have to set up a classpath properly so the JVM can find application code.

Let's define an expecco environment variable named CLASSPATH_BANKACCOUNT defining where the "Bank Account" code is actually located:

Expecco BankAccounts 001.png


Then let's define a "SetUp" block that actually adds the directory to JVM class path. A simple JavaScript block would do it:

execute

   JAVA::Java singletonInstance
       addToClassPath: (self environmentAt: 'CLASSPATH_BANKACCOUNT')    

This block has to be run before any other Java code using "Bank Account" classes is run. Putting it as test plan's pre-execution block !ref! might be a good way to ensure it.

Designing a test[Bearbeiten]

Once the class path is set up, we start designing an implementing tests. Let's start with a simple tests that create a two bank accounts and then make transfer from one account to the other. Then tests would check if the final balance on accounts is what one would expect.

The very simple test would be then:

  • create account A1 with initial balance 1000.
  • create account A2 with initial balance 1000.
  • transfer 500 from account A2 to account A1.
  • check that final balance of A1 is 1500
  • check that final balance of A2 is 500.
  • check that no exception was thrown.

We will encapsulate first three steps in to a special block, let's call it Create 2 accounts & make a transaction, which will take initial balances and amount to transfer from input pins and report final balances to output pins. In addition, it will report an eventual exception via exception output pin.

By separating this logic to a separate block we can easily create more tests with different value to test different scenarios like: to check that an exception is raised when there are not enough funds on a charged account.

So, in expecco, the very simple testcase outlined above would look like:

Expecco BankAccounts 002.png

Implementing the first test[Bearbeiten]

In order to implement the test as outlined above, we have to implement a block that actually call the Java API.

Java Browser/en plugin for expecco provides a simple browser to load and browse Java code directly from expecco environment. To open a Java Browser on "Bank Account" code, select PluginsJava BrowserOpen... from expecco menu and define a new Java browser workspace. A Java browser workspace is a folder where Java Browser stores all the Java code and sources. You can define as many workspaces as you like and switch between them. If you don't have a workspace for "Bank Account" yet, just enter an empty directory and new workspace will be created. Initially the workspace is empty, so to actually see the code of "Bank Account", we have add it's code and sources to the workspace. To do so, just click to Open Settings button in Java Browser window or select WorkspaceSettings from window menu. In Settings dialog, click to Add Library button and add Bank Account code. One added and confirmed (by pressing OK button), you may browse through the code, check what classes and methods are available and so on.

Expecco BankAccounts 005.png

Let's implement the Create 2 accounts & make a transaction block now. Just create a new Groovy block and write a little code that calls "Bank Account" Java API.

To make writing code a little bit easier, SmallSense/en plugin together with Java Browser/en plugin provides a simple completion support for Groovy. The completion engine takes information about available classes and methods from the Java workspace. In other words, if you have no Java browser workspace opened, the completion won't suggest any classes nor methods.

To trigger the completion, just press Ctrl-Space:

Expecco BankAccounts 006.png


The code of the block may be the following:

import exept.expecco.projects.examples.bankaccount.Bank;
import exept.expecco.projects.examples.bankaccount.Account;
// end of definitions -- do not remove this line unless imports above is 
empty

def execute() {
    Bank b = new Bank( "Some bank" );

    Account account1 = new Account( "Owner 1" );
    b.addAccount( account1 );
    account1.setBalance( initialBalance1.value() );

    Account account2 = new Account( "Owner 2" );
    b.addAccount( account2 );
    account2.setBalance( initialBalance2.value() );

    try {
        account1.credit(account2, amount.value() );
        exception.value( null );
    } catch ( TransactionException e ) {
        exception.value( e );
    }     

    balance1.value( account1.getBalance() );
    balance2.value( account2.getBalance() );
}

Now we have all bits together to implement and run the simple test. It passes.

Expecco BankAccounts 010.png

Debugging tests I[Bearbeiten]

One test passed. but let's create another one. Similar, but with different, extrem values. Let's try to transfer an awful lot of money so the balance of credited account would exceed the maximum allowed balance. According to a specification [!ref!] the transation should not proceed and an TransactionException should be thrown. The test may look as following:

Expecco BankAccounts 011.png

If you try to run it you will see it fails. Now it's time to figure out why and this is the point where Java Debugger/en plugin is useful. Basically, Java Debugger plugin allows you to debug code running in remote JVM - placing breakpoints, single-stepping through the code, inspecting values of variables and objects.

Back to our failing test. The code of a Groovy block likely correct. The actual transfer is done in method BankAccount#credit() [!ref!]. Let's put a breakpoint here and then single-step through the code until we reach the point where the actual computation is done.

To place a breakpoint, simply open a Java Browser, select class Account and method credit() and then put a breakpoint at the beginning of the method (by clicking in the editor, left to the line number):

Expecco BankAccounts 012.png

Now run the test again. A Java Debugger window should appear:

Expecco BankAccounts 014.png

The debugger shows a Java execution stack on the top, source code of the selected method in the middle and an inspector for this and for local variables in the bottom part. Let's single step a little bit further, into method Transaction#perform() to line 55. Use button Next to step-over to next line and Send to step-into called methods.

You may use the bottom inspector to inspect the value of amount or local variables. If you double-click to an object value as, say, source field of the transation object, a new inspector on that object is opened:

Expecco BankAccounts 015.png

The code around line 55 in Transaction.java reads as:

54    // Check if destination account would exeeded MAX_BALANCE after crediting.
55    if ((oldDestinationBalance + amount) > Account.MAX_BALANCE) {
56            throw new TransactionException("Maximuma ccount balance exceeded +" + source.getId());
57    }
58
59    long newSourceBalance = oldSourceBalance - amount;

It checks if the new balance on destination account would exceed the maximum and of so, just throw an exception as documented. By inspecting values of amount and oldDestinationBalance you may see that the values are what one would expect, so if you press Next button, the execution should enter the if body and throw an exception. If you actually do it, you'll see that the condition is satisfied and the execution proceeds to line 59.

This is clearly a bug in the application code (classical integer overflow in this case). So the test developer may just submit a bug to development team a be done with it.

Debugging tests II[Bearbeiten]

Let's write yet another test that tries to transfer a negative amount. The API documentation does not specify the behaviour in this case explicitly. The would look like the very first test except the amount would be -500 rather than 500 and the final balances would be the other way around.

Actually such a test would fail. As you may see, the code throws a ```TransactionException``` with rather unspecific message Internal error occired during transaction. The message is bit worrying as, if negative value is now allowed, the error message should say so. It could be that something else went wrong.

Expecco BankAccounts 017.png

To find out, we may again use Java debugger plugin and place an exception breakpoint, a special kind of breakpoint that stops program execution when an exception of specific type is thrown. To do so, go to PluginsJava DebuggerBreakpoint List. This opens a little window displaying all Java breakpoints, including line breakpoints we have used earlier. Use context menu (right-click in the list) to add an exception breakpoint:


Expecco BankAccounts 018.png

A dialog will appear where you can specify exception class name - exept.expecco.projects.examples.bankaccount.TransactionException in this case. Be aware, it has to be a fully qualified Java class name. Also, you have to tick both Caught and Uncaught checkboxes, as the Java bridge code catches all exceptions.

Expecco BankAccounts 020.png

Now run the test again. A debugger should appear, stopping at line 65 in Transaction.java. The code here simply catches all exceptions and re-throw a TransactionException. So still it's not clear what is the real cause. To find out, let's check what is the value of the original exception, stored in variable e (just click or double-click to e in bottom left part of the debugger window which shows local variables).

It's a java.security.InvalidParameterException. Let's just put another exception breakpoint, now for java.security.InvalidParameterException and run the test again. This should reveal the origin of the problem.

Expecco BankAccounts 021.png

If you run it again, you may see that the exception is thrown in Transaction#check() if the amount specified is less than zero.

Wrap-up[Bearbeiten]

The Java browser plugin, Java Debugger plugin and SmallSense plugin can make test development using Groovy block easier:

  • Java browser plugin provides a way to browse Java code right from the expecco environment, without need of external, third-party IDE.
  • SmallSense plugin provides a simple completion support to Groovy block editor, making editing easier.
  • Java Debugger plugin provides in-expecco debugging facilities to debug Java code running system under test, making test debugging easier.

These plugins are not necessary to use Groovy blocks, however, working with complex Java code might tricky when it comes to test debugging. While it is possible to use third-party Java IDEs and debuggers, the added value of these plugins is tight integration with expecco.

For more information, refer to:

Download[Bearbeiten]

TODO[Bearbeiten]

  • cleanup You / we
  • Upload standalone .ets and .zip with Eclipse project Java doc somewhere
  • Upload Java doc somewhere
  • Fix crossrefs (to javadoc and other documents), once above get sorted.



Copyright © 2014-2024 eXept Software AG