execute
Description
Execute one or more processes. Most likely, these will be the processes being tested.
Attributes
List of execute()
Attributes
execute()
for Database
- >> REF:
sql: - >> TYPE: string
sql-script: - >> TYPE: string
sql-procedure: - >> TYPE: string
parameters: - >> TYPE: list of strings
execute()
for Informatica
- >> REF:
error-id: - >> TYPE: string
execute()
for Java Executable
java-class: - >> TYPE: string REQUIRED
arguments: - >> TYPE: list of strings. If present, minimum # of items: 1
exit-code: - >> TYPE: integer
run-id: - >> TYPE: string
system-properties: - >> TYPE: object (key-value pairs, comma-separated)
execute()
for Runtime Executable
executable: - >> TYPE: string
Individual execute()
Attributes
execute() for Database Context
[Database Feature Module - Configuration properties not listed here.]
connection-id:
- Corresponds to
id
property in the@Database
annotation. - Any value other than one that corresponds to the
id
property in the@Database
annotation is not allowed.
mode:
- Corresponds to one member in the list of
modes
, found in the@Database
annotation. - Any value other than one that corresponds to one of the
modes
listed in the@Database
annotation is not allowed.
sql:
- Literal text of an SQL statement to execute.
- The database used by the SQL statement should be declared with the @Database annotation before the test method or test class.
sql-script:
- Name of an SQL script file to execute.
- The file is located in the
sql/
folder, a sibling to the ETLUnit test. - The SQL script file should have an "
.sql
" file extension. - The value of
sql-script
should exclude the.sql
file extension.
sql-procedure:
- Name of an SQL stored procedure to run.
parameters:
- A list of strings.
- These are parameters that will be passed to the stored procedure.
- Not valid without
sql-procedure
.
execute() for Informatica Context
[All but the last property below originate in the ETLAgent project.]
domain-defaults:
client-type:
agent:
host-name:
host-port:
informatica-bin-directory:
security-domain:
working-root:
username:
password-encrypted:
A string
password:
client-version:
connectivity-host:
connectivity-port:
default-domain:
domains:
- JSON object, key-value pairs. Each includes these:
<domain-name>
[same available properties as domain-defaults above, plus:]
default-repository:
repositories:
- JSON object, key-value pairs. Each includes these:
<repository-name>:
default-web-services-hub:
default-integration-service:
integration-services:
web-services-hubs:
- JSON object, key-value pairs. Each include these:
<web-service-hub-name>:
host-name:
host-port:
workflow:
folder:
task:
informatica-integration-service:
informatica-domain:
informatica-repository:
context-name:
- Compare to context-name in the stage operation.
log-name:
context:
source-files:
lookup-files;
run-instance-name:
parameters:
- Unique list of JSON objects, (key-value pairs). Each include these:
<parameter-label>:
scope:
parameter-name:
parameter-value:
informatica-integration-service:
informatica-domain:
informatica-repository:
error-id:
- If an error occurs during workflow execution, the error ID to return in the CLI.
execute() for Java Executable Context
java-class:
- Required.
- A string.
- The qualified name of your Java class.
- In other words, the Java class name preceded by any package hierarchy.
- e.g.:
java-class: 'MyJavaClass'
java-class: 'com.sonicdrivein.etl.edw.ListParameters'
arguments:
- List of strings.
- Arguments to pass to the Java
main
method. - e.g.:
arguments: ['arg1','arg2']
exit-code:
- An integer.
- The expected exit code from the Java class.
- If execution of the Java class errors out, you may not know about it unless you check the logs.
- But if you provide an
exit-code
of 0, and execution of the Java class errors out, the test will error out. - An unmatched exit code returns error '
ERR_JAVA_EXECUTION_ERROR_BAD_RETURN_CODE
.'
run-id:
- A string.
- You can manually find the run-id in the test's log.
system-properties:
- An object (key-value pairs).
- These become system properties that become available to the Java class when it is executed.
- TODO: Make this code accessible? There is sample code in the
java-samples
module of theetlunit-specific-examples
project on Bitbucket.
Special Instructions
execute()
for Java Executable
In order to be able to run a Java class in your ETLUnit project, here are some tips that may help.
- Include the
etlunit-execute
dependency in your POM.
<dependencies>
<dependency>
<groupId>org.bitbucket.bradleysmithllc.etlunit</groupId>
<artifactId>etlunit-execute</artifactId>
<version>${etlunit.project.version}</version>
</dependency>
</dependencies>
- The
java-executor
feature must be configured for your project.- The default file for defining your project's configuration is
etlunit.json
, located in foldersrc/test/resources/config
. - You may also place the configuration information in another file, (e.g.,
java.json
) so that you can run your Java tests in another profile. In this case the profile name would be "java
." TODO: Fix link. SEE the ETLUnit Test Profiles page for more information about profiles.
- The default file for defining your project's configuration is
- At a minimum, your profile configuration file must declare
java-executor
as one of the installed features of your project.
{
"install-features": ["java-executor"],
"features": {}
}
- TODO: Make this code accessible? There is sample code in the
java-samples
module of theetlunit-specific-examples
project on Bitbucket. - Place your Java source code under folder
src/main/java
. You may use packages if you wish. - ETLUnit will execute a Java class only if it has a
main
method. - When you run a Maven compile or package on your project, binaries for Java classes you wrote will be written to
target/classes
. Package structure will be maintained. - Out-of-the-box, ETLUnit will only be able to find your Java classes when the tests are run by Maven from the command line. Running an ETLUnit test from Maven looks like the following:
mvn test -Detlunit-test=#my_java_test
- If you can recognize it, the test name is preceded by the pound sign ("#"), which is part of the command line syntax to run a test method (contrast this with the syntax to run a test package, a test class, or an operation). Not all special symbols used in the CLI will work in the context of the Maven test command. TODO: Fix link. SEE the ETLUnit CLI page for more information on running tests from the ETLUnit command shell.
- That said, you can run Java classes from the command shell if you manually reconfigure the batch file that starts the command line interface ("CLI").
- There are two batch files that are used to start the shell. They both reside in folder
bin/
under your project root.- Batch file "
etlunit
" will be invoked when your command shell is a Unix-like shell, like BASH. - Batch file "
etlunit.bat
" will be invoked when your command shell is the Windows command shell.
- Batch file "
This documentation was written while working only on a Windows machine. Other operating systems are not represented here, although ETLUnit runs on them quite well. My apology.
# Replace the following line in the script: java -classpath target\classes;target\test-classes -Djava.ext.dirs=lib org.bitbucket.bradleysmithllc.etlunit.cli.CliMain # with this line: java -classpath target\classes;target\test-classes -Djava.ext.dirs=lib -Djava.class.path=/c/src/MY_PROJECT/target/classes org.bitbucket.bradleysmithllc.etlunit.cli.CliMain # Be sure to make the java.class.path property's path reflect the location of your project.
rem Replace the following line in the script: java -classpath target\classes;target\test-classes -Djava.ext.dirs=lib org.bitbucket.bradleysmithllc.etlunit.cli.CliMain rem with this line: java -classpath target\classes;target\test-classes -Djava.ext.dirs=lib -Djava.class.path=.;C:\src\MY_PROJECT\target\classes org.bitbucket.bradleysmithllc.etlunit.cli.CliMain rem Be sure to make the java.class.path property's path reflect the location of your project.
- When your Java class has completed:
- You can find standard out and error output in a location like this:
target/generated-sources/log/<testClass>/<testMethod>/0_execute/
- You can find html reports in a location like this:
target/html-reports/<hash>
- You can just run the report ("
r
" or "report
" from the CLI) and see the contents of the log files from there.
- You can find standard out and error output in a location like this:
- Once all the configuration pieces are in place, you will be able to run an ETLUnit test that uses the
execute
operation in the Java Executor context.- Your test will succeed when run using
mvn test
. That means that continuous integration batch tests that make use of Maven to run your project's tests will not break. - Your test will succeed when run in ETLUnit's CLI.
- Your test will succeed when run using
Once you've changed the script files to enable Java Executor in the CLI shell, you may want to back them up. Whenever you repackage your ETLUnit project (e.g., mvn clean package -DskipTests
) these two files are replaced.
- Create a folder, say "
archive
," in the root of your project. It will be a sibling to foldersrc/
. - Copy
etlunit
andetlunit.bat
there.
Examples
execute()
for Database Example
The following example uses custom FML to do its job. There are three FML files included.
- The source data file has only one column. By providing FML for the single column source, a column list does not have to be provided.
- The test will fail if FML is not provided for the stage operation's target database file,
ADDRESS_TYPE
. - The target data file in the assert operation uses its own two-column FML description.
The assert operation's source-reference-file-type property narrows the count of columns that will be compared with the target to just two.
TODO: Make this project accessible? This example is from the sql-database-samples
module of the etlunit-specific-examples
project in Bitbucket.
/*-- DESCRIPTION --*/
/*-- TIMESTAMP --*/
MAILING
PHYSICAL
BILLING
CREATE TABLE dbo.ADDRESS_TYPE ( ADDRESS_TYPE_ID SMALLINT NOT NULL , DESCRIPTION VARCHAR(256) NULL , POPULATION_DATE DATETIME NOT NULL ) ;; ALTER TABLE dbo.ADDRESS_TYPE ADD CONSTRAINT XPKADDRESS_TYPE PRIMARY KEY CLUSTERED (ADDRESS_TYPE_ID ASC) ;; CREATE TABLE dbo.ADDRESS_TYPE_IV ( ADDRESS_TYPE_ID SMALLINT NOT NULL , DESCRIPTION VARCHAR(256) NULL , POPULATION_DATE DATETIME NOT NULL ) ;; ALTER TABLE dbo.ADDRESS_TYPE_IV ADD CONSTRAINT XPKADDRESS_TYPE_IIV PRIMARY KEY CLUSTERED (ADDRESS_TYPE_ID ASC) ;; CREATE PROCEDURE CopyBillingAddressID_TypeToIV @ID smallint, @Type varchar(256) = NULL AS INSERT INTO address_type_iv SELECT * FROM address_type WHERE ADDRESS_TYPE_ID = @ID AND DESCRIPTION = ISNULL(@Type, DESCRIPTION) ;;
{ "flat-file" : { "format-type" : "delimited", "row-delimiter" : "\n", "column-delimiter" : "\t", "null-token" : null, "columns" : [ { "id" : "ADDRESS_TYPE_ID", "type" : "SMALLINT", "length" : 5, "basic-type" : "integer", "default-value" : { "initial-value" : 2, "increment" : 2, "modulus" : 32768 } }, { "id" : "DESCRIPTION", "type" : "VARCHAR", "length" : 256, "basic-type" : "string", "default-value" : { "initial-value" : 3, "increment" : 3, "expression" : "$strings.constrain(\"DESCRIPTION[${defaultValue}]\", 256)" } }, { "id" : "POPULATION_DATE", "type" : "TIMESTAMP", "length" : 23, "basic-type" : "string", "default-value" : { "initial-value" : 4, "increment" : 4, "expression" : "$math.add(2000, $math.modulo($defaultValue, 100))$numbers.leftPad($math.add(1, $math.modulo($defaultValue, 12)), 2)$numbers.leftPad($math.add(1, $math.modulo($defaultValue, 28)), 2)" }, "format": "yyyyMMdd" } ], "primaryKey" : [ "ADDRESS_TYPE_ID" ], "orderBy" : [ "ADDRESS_TYPE_ID", "DESCRIPTION", "POPULATION_DATE" ] } }
{ "flat-file" : { "format-type" : "delimited", "row-delimiter" : "\n", "column-delimiter" : "\t", "null-token" : null, "columns" : [ { "id" : "DESCRIPTION", "type" : "VARCHAR", "length" : 256, "basic-type" : "string", "default-value" : { "initial-value" : 3, "increment" : 3, "expression" : "$strings.constrain(\"DESCRIPTION[${defaultValue}]\", 256)" } } ] } }
{ "flat-file" : { "format-type" : "delimited", "row-delimiter" : "\n", "column-delimiter" : "\t", "null-token" : null, "columns" : [ { "id" : "ADDRESS_TYPE_ID", "type" : "SMALLINT", "length" : 5, "basic-type" : "integer", "default-value" : { "initial-value" : 2, "increment" : 2, "modulus" : 32768 } }, { "id" : "DESCRIPTION", "type" : "VARCHAR", "length" : 256, "basic-type" : "string", "default-value" : { "initial-value" : 3, "increment" : 3, "expression" : "$strings.constrain(\"DESCRIPTION[${defaultValue}]\", 256)" } } ], "primaryKey" : [ "ADDRESS_TYPE_ID" ], "orderBy" : [ "ADDRESS_TYPE_ID" ] } }
@Database(id: 'edw', modes: ['src'])
class Sql_Demo{
@Test
@Description(description:'Demo sql-procedure with parameters')
sql_demo_6(){
stage(
source: 'ADDR_TYPE_DESC',
target-table: 'ADDRESS_TYPE',
reference-file-type: {
id: 'addr_desc'
}
);
execute(
sql-procedure: 'CopyBillingAddressID_TypeToIV',
parameters: ['6', 'BILLING']
);
assert(
source-table: 'ADDRESS_TYPE_IV',
source-reference-file-type: {
id: 'address_type',
column-list-mode: 'exclude',
column-list: ['POPULATION_DATE']
},
target-reference-file-type: 'addr_id_desc',
target: 'BILLING_ADDR_TYPE_ID_DESC'
);
}
}
/*-- ADDRESS_TYPE_ID DESCRIPTION --*/
/*-- INTEGER TIMESTAMP --*/
6 BILLING
execute()
for Informatica Example
@Database(id: 'qpt_pet', modes: ['src'])
class gap_filler_v1andv2 {
@Test
columnsLoadInOrder() {
stage(
source: 'BUCKET_GAP_FILLER_FF_COLM_ORD',
connection-id:'qpt_pet',
target-table: 'BUCKET'
);
execute(
workflow: 'wkf_GAP_FILLER_EXTRACT_V2_BUCKET',
folder: 'EDW_QPT_BUCKET',
context:
{
pet-connection-src: 'informatica.connections.qpt_pet.src'
}
);
assert(
target: 'FF_BUCKET_V2_COL_LOAD_ORDR',
source-file: 'FF_BUCKET_V2.txt',
reference-file-type: 'FF_BUCKET_V2'
);
}
}
execute()
for Java Executable Example
TODO: Make this code accessible? SEE the java-samples
module of the etlunit-specific-examples
project in Bitbucket.
To get this to work using the CLI, follow the instructions above for ETLUnit CLI script modifications.
The following Java executable example has several pieces. The log assertion annotation is included to give the exercise a mite more meaning.
- Project folder structure for the artifacts used by this example
- Source for Java class
SystemInfo
- Should be placed under
src/main/java
- Should be placed under
- Log expression file
fandango_surprise.expr
- In this case, contains a fragment of the log contents representing an expected log excerpt string.
- Test class
java_demo.etlunit
package com.toneralight.etl;
import java.util.Enumeration;
import java.util.Properties;
public class SystemInfo {
public static void main(String[] args) {
System.out.println("Number of args passed in: " + args.length);
if(args.length > 1){
String expectedPropName = args[0];
String expectedPropValue = args[1];
String foundPropVal = System.getProperties().getProperty(expectedPropName);
if(thickStr(foundPropVal)){
if(foundPropVal.equals(expectedPropValue)){
System.out.printf("Property %s has expected value %s\n", expectedPropName, expectedPropValue);
}else{
System.out.printf("Property %s has unexpected value %s\n", expectedPropName, foundPropVal);
}
}else{
System.out.printf("Argument %s does not seem to be a property.\n", foundPropVal);
}
}
private static boolean thickStr(String val){
if(val==null) return false;
if(val.length() < 1) return false;
return true;
}
}
}
Property fandango has unexpected value no
class java_demo {
@LogAssertion(
expected-logs: [
{
assertion-mode: 'contains',
expected-log-file: 'fandango_surprise',
classifier: 'standard-out'
}
]
)
@Test
pass_system_properties(){
execute(
java-class: 'com.
toneralight
.etl.SystemInfo',
arguments: ['fandango', 'yes'],
exit-code: 0,
run-id: 'system_properties_fandango',
system-properties: {
fandango: 'no'
}
);
}
}
execute()
for Runtime Executable Example
Not implemented at this time.