Groovy Contract Tests Manual

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sapien purus, congue a tincidunt non, mollis vitae diam. Fusce pharetra massa interdum nisl ultrices mattis. Cras eget est ultricies magna auctor condimentum. Phasellus sed elit erat, a ultricies arcu. Proin vitae volutpat ante. Quisque porta tempor elit, non aliquam tortor sodales nec. Sed imperdiet metus sed orci adipiscing faucibus. Nulla facilisi. Nulla massa tortor, dapibus a vehicula vel, cursus vel mi. Integer sed lacus velit. Etiam dignissim varius turpis ut ullamcorper. Integer lobortis imperdiet dui, ut porta nulla interdum ac. Nulla neque lorem, bibendum et venenatis a, convallis in arcu. In sagittis neque ac mauris venenatis id elementum elit lacinia. Phasellus porttitor turpis eu ipsum pharetra eleifend. Integer ac magna sit amet mi luctus scelerisque at a odio. Quisque sed mi nibh, ac pretium felis. Nunc congue sapien sit amet ipsum elementum ac euismod justo mollis. Etiam dictum elementum libero sed sagittis.

1. Quick start guide

Contract test configuration files are written in the Groovy scripting language (parsed by ConfigSlurper). Groovy features a Java-like and most Java code will work in Groovy without modification. For more information on Groovy, see http://groovy.codehaus.org.

1.1 Introduction to Groovy

Take a moment to familiarize yourself with the following Groovy constructs.

Programming Construct Example
To create a map 
map = [key1 : value1, key2 : value2]
To declare a new list
list = [item1, item2]
 
To call static contract test helpers

Note: These methods are evaluated at the time of the user query.



 Tip: 

You can avoid repeating the same prefix by grouping statements inside of curly braces.

For example:
Before:

                                        // path to bundle jar - property is set by ant - leave it as it is
                                        testsuite.bundleJar=System.getProperty("bundleJar")
                                        
                                        
                                        // ValidateApiOpTests
                                        testsuite.Validate.iterations="3"
                                        
                                    
After:
testsuite {
                                           
                                        // path to bundle jar - property is set by ant - leave it as it is
                                            bundleJar=System.getProperty("bundleJar")
                                        
                                           
                                        // ValidateApiOpTests
                                            Validate.iterations="3"
                                        }
                                    
There is a limitation, however: A prefix can only be defined this way once per configuration file. So in the previous example, there cannot be more than one block in the file with testsuite as the prefix. For example, the following is invalid:  testsuite{...} testsuite{...}

In key-value pairs, value items are typically "quoted strings" . Also note that types of properties in Groovy scripts are defined implicitly, so there is no need to type java.util.Map or  List.

1.2 Locating Configuration Files and Proprietary JARs

Configuration Files

Contract test configuration files (groovy files) are loaded as classpath resources with connector class full qualified name as basic prefix:

Main configuration file
${connectorName}/config/config.groovy
Optional configuration file for resource specific configurations
${connectorName}/config/${configuration}/config.groovy
Private Main configuration file
${connectorName}/config-private/config.groovy
Private Optional configuration file for resource specific configurations
${connectorName}/config-private/${configuration}/config.groovy

Environment variables and properties should be defined as follows:

  • Set connectorName to a full qualified name of your connector e.g   org.identityconnectors.ldap.LDAPConnector
  • Replace  { $ configuration} with resource-specific configuration information. For example, a databasetable connector can run against various databases, and in the case of a MySQL configuration, the folder name would be .databasetable-mysql.
  • Connector build script copies the configuration files from your connector project folder(src/test/config) and default private configuration folder(user.home/.connectors/bundle-name/config) to be present on classpath of the unit and contract tests

 Note: Properties defined in Main configuration files are overridden if new definitions are defined in subsequent Optional configuration files.

Proprietary JARs

Proprietary JARs should not be checked in to a versioning system. They are located in  /lib directories in configuration-specific folders:

{$user-home}/.connectors/bundle-name/lib
{$user-home}/.connectors/bundle-name/lib/{$configuration}

1.3 Configuring a local Connector

Define the following five properties in the connector's property file:

{$user.home}\.connectors\bundle-name\config\${connectorName}\config-private\config.groovy

Note: The following script fragments are from the DatabaseTable connector's configuration files .

  1. Define the  testsuite.bundleJar property:

    // path to bundleJar property is set by ant - leave it as it is
    testsuite.bundleJar=System.getProperty("bundleJar")

    If the connector is a remote connector on a Connector Server , replace testsuite.bundleJar with the following:

    testsuite.serverHost=" hostAddress"
    testsuite.serverPort= portNumber // e.g. 8759
    testsuite.serverKey=" connectorServerKey" //default connector server key is "changeit"

  2. Define properties which identify connector.

    // propertis bundleName and bundleVersion are set by ant - leave it as it is
    testsuite.bundleName=System.getProperty("bundleName")
    testsuite.bundleVersion=System.getProperty("bundleVersion")
    testsuite.connectorName="org.identityconnectors.mysqluser.MySQLUserConnector"


  3. Define connector.{$property.name} for each annotated connector configuration bean property (in the class Configuration interface).

    // Connector configuration
    connector.driver=" com.mysql.jdbc.Driver"
    connector.keyColumn=" ACCOUNTID"
    connector.passwordColumn=" PASSWORD"
    connector.DBTable=" idm_sync"
    connector.connectionUrl=" jdbc:mysql://localhost/idm_sync"
    connector.login=" foo"
    connector.password=" foo "

    For more information 
    See  connector configuration properties and  defining properties in the In-depth Guide to learn
    • how properties lookup works
    • how to define properties values using static/lazy init
    • what properties types are possible


  4. Define invalid configurations for ValidateApiOpTests and TestApiOpTests. Follow the previous links for explanation, configuration syntax of these API operation tests.

    // Test will go through 3 iterations
    Validate.iterations="3"

    // Incorrect connector configuration for ValidateApiOpTests

       // The following property will be used in the first iteration (must be at least one)
      connector.i1.wrong.host=""

       // The following property will be used in the second iteration
      connector.i2.wrong.login=""

       // The following property will be used in the third iteration
      connector.i3.wrong.password=""



  5. Define the properties necessary to pass SchemaApiOpTests.
    1. Define the list of supported object classes by connector. (See ObjectClass.java for up-to-date object class types.):

      // Database table connector supports only object class ACCOUNT
      testsuite.Schema.oclasses=['__ACCOUNT__']

    2. Define the list of attributes for each supported object class:

      // List of ALL attributes of object class ACCOUNT for database table connector
      testsuite.Schema.attributes.__ACCOUNT__.oclasses=['__NAME__', '__PASSWORD__', 'MANAGER', 'MIDDLENAME', (continued on next line)
         'FIRSTNAME', 'LASTNAME', 'EMAIL', 'DEPARTMENT', 'TITLE', 'AGE', 'SALARY', 'JPEGPHOTO']

    3. Define every attribute of each object class:

    4. // definition of attribute __NAME__ of object class ACCOUNT for database table connector
      testsuite.Schema.__NAME__.attribute.__ACCOUNT__.oclasses=[
         type: java.lang.String.class,
         readable: true,
         createable: true,
         updateable: true,
         required: true,
         multiValue: false,
         returnedByDefault: true
      ]
    5. Define supported object classes by operations. Must contain exactly the operations that are implemented by the connector:

      // object classes supported by operations for database table connector
      Schema.operations=[
         GetApiOp: ['__ACCOUNT__'],
         SchemaApiOp: ['__ACCOUNT__'],
         ValidateApiOp: ['__ACCOUNT__'],
         CreateApiOp: ['__ACCOUNT__'],
         SearchApiOp: ['__ACCOUNT__'],
         DeleteApiOp: ['__ACCOUNT__'],
         ScriptOnConnectorApiOp: ['__ACCOUNT__'],
         UpdateApiOp: ['__ACCOUNT__'],
         AuthenticationApiOp: ['__ACCOUNT__'],
         TestApiOp: ['__ACCOUNT__'],
         SyncApiOp: []
      ]
  6. ( Optional) Define other Optional properties.

1.4 Running tests


Easy Steps for Running and Troubleshooting Contract Tests

  1. Run the command ant in the /framework and /bundles/fooconnector directories. This will compile the Framework and Connector classes.
  2. To run tests, type the command ant run-contract-tests  from the connector directory (for example, /bundles/fooconnector).
  3. To create an HTML summary of the test results, type the following command: ant report-junits . The summary will be saved to the /reports subdirectory.
  4.  Note: When you type ant report-junits a new connector.jar is created in a ${connector.dir}/reports directory. This newly created JAR file contains all the connector classes (except JUnit tests), all JARs from the ${bundle.dir}/lib directory, and proprietary JARs from the  ${user.home}/.connectors/bundle-name/lib directory.

Troubleshooting contract-test.groovy files
  • When troubleshooting contract-test.groovy files, remember the following:
    • Contract test property names are case sensitive
    • Contract test property names must be valid Java identifiers.
  • Verify the following standard Groovy imports . Groovy contract tests support the creation of special object types. By default Groovy imports six packages and two classes: java.lang.*,  java.util.*,  java.io.*,  java.net.*,  groovy.lang.*, groovy.util.*, java.math.BigInteger, java.math.BigDecimal .  If you want  to use additional types, add an import statement your configuration file.

  • Verify the following contract-test-specific imports . Don't forget to add the following imports when you use Lazy property evaluation. (You can optionally add additional types.)
    import org.identityconnectors.contract.data.groovy.Lazy;
                                                    import org.identityconnectors.contract.exceptions.ObjectNotFoundException;
                                                    
                                                

Detailed Steps for Running Contract Tests

Before You Begin

Verify the following:
  • Make sure that framework, contract tests and the connector to test are built by ant . A  /dist folder is created as a result.
  • Verify that either fooconnector/build.xml or fooconnector/build.properties contains the line  contracts.run=true. This line enables contract tests to start.

Basic Usage

Run the contract test suite from the connector directory with the following command:
ant run-contract-tests
                        
                    
Or, if the connector has more test configurations:
ant -DtestConfig=
                        conf1 run-contract-tests
                        
                    
where conf1 is the configuration name. In this case, tests will use the {$bundle.dir}/config/${connectorName}/ conf1/config.groovy for non confident configuration settings and {$user.home}/.connectors/bundle-name/config/${connectorName}/config-private/ conf1/config.groovy for confident (private) configuration settings files.


Export of Generated Test Parameters

During the test many parameters are generated that are used as input data for the tests. These can be exported to a property file that is useful when debugging connectors' contract tests.

To generate the snapshot:
                        // run contract tests and store all parameters (attributes values) used by tests in 
                        test.properties
                         file
                        ant -Dtest.parameters.outFile=generated.properties run-contract-tests
                        
                    

Running Contract Tests in Eclipse

Create a new JUnit run configuration and set values on the Test tab according to the following screenshot. Don't forget to set JUnit 4 Test runner .

test.jpg

On the  Arguments tab, add the following VM arguments :

  • -DtestConfig=mysql  - Optional argument. Only set if you want to run particular configuration.
  • -DconnectorName=org.identityconnectors.databasetable.DatabaseTableConnector  - This is the project name from build.properties.
  • - DbundleJar=dist/org.identityconnectors.databasetable-1.0.x.jar  - Set the relative path to the tested connector JAR. The path is relative to the working directory.
  • -DbundleName=org.identityconnectors.databasetable  - Set the bundle name, that should be specified in build.properties.
  • -DbundleVersion=1.0.x - Set the version in the following format: MAJOR.MINOR.SVN_REVISION
    In case SVN_REVISION is not set, we can use 'x' instead.
Important!  Do not forget to change the Working directory to the tested connector project.

arguments.jpg



Add all projects connector dependencies to the Classpath so that you can debug them all, and also add references to all required proprietary JARs.

classpath.jpg


1.5 Configuring Connector on Connector server

Easy Steps
  • Add testsuite.serverHost, testsuite.serverPort, testsuite.serverKey to the private configuration  ( ${user.home}/.connectors/bundle-name/config/${connectorName}/config-private/config.groovy). The rest of configuration is the same as  steps 2 through 5 for local connectors .
  • Add a build.xml file to the bundle directory with the following content:
  • <project name="connector-ad" default="all">
                                                 <property name="framework.dir" value="../../framework"/>
                                                 <property name="bundles.dir" value="../"/>
                                                 <property name="contracts.run" value="true"/>
                                                 <import file="${framework.dir}/connector_build.xml"/>
                                                </project>
                                                
                                                
                                            
  • Run the test using  ant run-cs-contract-tests
    or with additional connector server properties which will override those specified in configuration file ant -DserverHost=host -DserverPort=8759 -DserverKey=changeit run-cs-contract-tests

In this section Connector Server (formely called Gateway) will be referred as the Server. The Server contains connectors that are called by the connector framework through a remote facade . (The facade handles remote calls transparently.)

First please review the Quick start guide  (if you have not done that already).

To run tests against connectors running behind the Server, it is necessary to create a new configuration. (The  framework/test-contract project is recommended, but it is generally possible to configure it for every project which has build.xml and imports connector_build.xml.) 

Set the following properties in ${bundle.dir}/config/${connectorName}/config.groovy: and the private part to
${user.home}/.connectors/bundle-name/config/${connectorName}/config-private/config.groovy:

There are currently no special properties necessary to identify a connector behind the Server, because there must be exactly one connector behind the Server and that one is tested.

Before running tests, compile the contract test suite by running ant from within framework/test-contract. This step is necessary because the run-contract-tests ant target creates a new connector.jar that includes proprietary JARs. This is not necessary for Connector Server testing and it will be updated in the near future.

Make sure the Server is running on the host and port that you specified in the properties, and that the connector is running behind the Server. All libraries upon which the connector depends must be available to the Server on the Server classpath.

Tests are run from the bundle's directory using command:

ant run-cs-contract-tests
or with additional connector server properties which will override those specified in configuration file ant -DserverHost=host -DserverPort=8759 -DserverKey=changeit run-cs-contract-tests
Running tests on Connector Server inside Eclipse

1.6 Lazy evaluation helper methods

These methods are evaluated just in time of call.

Lazy.random()

Uses RandomGenerator's pattern as an argument for dynamic generation of random string or other types (second argument). Escaping works the following way:

Lazy.random("AAA\s\u\p\e\rAAA") // generates XIOsuperBYK, use \ to generate a constant character

To generate certain types, use: (requirement, the given type shall have a constructor accepting strings.

Lazy.random("###\\.##", Long.class) // generates a random Long value

Lazy.get()

It acquires the argument property. This is useful, when on the right hand side of a property there is needed a value of another one, for instance:
    propertyA = "constant"
    propertyB = Lazy.get("propertyA")