Integrating TestNG with TestRail
TestNG (opens in a new tab) is a popular JAVA testing framework which is used by many teams for both unit and end-to-end testing using tools such as REST Assured, Selenium WebDriver, Playwright, etc.
Railflow provides a convenient JAVA annotations package for TestNG framework which enables users to integrate their TestNG project with TestRail in a variety of flexible ways. Railflow TestNG Annotations package provides the following capabilities
Test Mapping
: Map TestNG tests existing tests in TestRailAttach Screenshots
: Attach screenshots and arbitrary attachments to the test case results in TestRail.Custom Fields
: Support for TestRail custom fields.TestRail Entities
: Update / Create Test Plans, Runs, Milestone, Tests, ResultsCI Application
: Support for Jenkins, TeamCity, Gitlab, Github, etc.
Getting Started
When using the Railflow annotation package, TestNG produces an enriched xml test report railflow_report.xml
. This report is then processed by Railflow CI Plugins or the CLI to upload the tests and test results to TestRail.
Maven Setup
This is example is using Maven as the build tool. You can use any other build tool like Gradle, Ivy, etc.
Add the Railflow TestNG dependency into pom.xml
:
<dependency>
<groupId>io.railflow.annotations</groupId>
<artifactId>railflow-testng-annotations</artifactId>
<version>0.5</version>
<scope>test</scope>
</dependency>
Configure Surefire Plugin
Then, configure Maven Surefire plugin
. This together with the Railflow dependency will generate an enriched report railflow_report.xml
in the target/surefire-reports
directory during mvn test
. This file contains additional test metadata that will be consumed by Railflow CLI or Railflow CI plugins for uploading tests and test results to TestRail.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<properties>
<property>
<name>listener</name>
<value>io.railflow.annotations.testng.RailflowReporterio.railflow.annotations.testng.RailflowReporter</value>
</property>
</properties>
</configuration>
</plugin>
Railflow Annotations
Railflow annotations package allow flexible mapping of TestNG tests to TestRail, attach screenshots, and configure TestRail custom fields. The package provides a number of annotations that can be applied at the class or method level.
Before using the Railflow annotations, you should think about how you want to map your TestNG tests to TestRail. Railflow provides two mapping options TESTNG
and TESTNG_STEPS
which treat each test method as a single test case or as a test step within a test case respectively.
The Railflow annotations behavior differs based on the mapping option selected. Read this section carefully to understand how to use the annotations correctly. If something is not clear, please contact our support team.
The two mapping options are exposed in the Railflow CLI and CI plugins (Jenkins, TeamCity). The CLI and CI plugins will parse the railflow_report.xml
file and upload the tests and test results to TestRail based on the mapping option selected.
TestNG Mapping
The TESTNG
option treats each test method
as a single testcase
. This means that when Railflow exports tests results to TestRail, each test method will be mapped to a separate test case in TestRail.
The Railflow annoations pacakge io.railflow.annotations.Railflow
has a number of attributes which can be applied at the class
or method
level.
Class Level
When TestNG classes use Railflow Class level attributes, the class level attributes are applied to the test results of methods inside the class
.
Name | Description |
---|---|
title | name for the subsection which contains the test in TestRail, if not defined |
testrailIds | not applicable for TestNG mapping + Class level annotations mix |
caseFields | array of test case field label/value pairs, e.g. @CustomField(name="My custom case field", value="Railflow rocks") |
resultFields | array of test result field label/value pairs, e.g. @CustomField(name="My custom result field", value="Railflow rocks") |
caseType | name of the case type for a test in TestRail, e.g. Automated |
casePriority | name of the case priority for a test in TestRail, e.g. High |
jiraIds | array of Jira issue IDs, which will be set as refs in TestRail |
smartFailureAssignment | array of user email IDs, each failed test in the class will be assigned to one of these users in a round-robin fashion |
Code Example: Using the attributes above, the class level attributes will be passed to each of the test methods in the class.
package io.railflow.annotations.demo;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.testng.Assert;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import io.railflow.annotations.testng.CurrentTest;
import io.railflow.annotations.testng.RailflowReporter;
@Listeners(value = { RailflowReporter.class })
//class level annotation
@Railflow(title = "Railflow on the class level", jiraIds = { "ISSUE-42", "ISSUE-43" }, caseType = "Automated", casePriority = "Critical",
caseFields = {@CustomField(name = "required text field", value = "class value"), @CustomField(name = "estimate", value = "42s") },
resultFields = {@CustomField(name = "Custom field", value = "result from class annotations")},
smartFailureAssignment = { "[email protected]", "[email protected]" })
public class RailflowDemo {
@Test
public void test() throws IOException {
CurrentTest.addAttachment("my log.txt", "something".getBytes(StandardCharsets.UTF_8));
}
@Test
public void test_failed() throws IOException {
CurrentTest.addAttachment("my log.txt", "something".getBytes(StandardCharsets.UTF_8));
Assert.fail("oops");
}
}
How Test Results Appear in TestRail
Method Level
Sometimes you do not want to apply the same attributes to all the test methods in a class. In such cases, you can use the Railflow annotation at the method level. Method level can be used to override the class level attributes and can be used together.
Name | Description |
---|---|
title | test title, if not specified, test method name is used |
testrailIds | array of TestRail test IDs into which the result of this method will be added |
caseFields | array of test case field label/value pairs, e.g. @CustomField(name="My custom case field", value="Railflow rocks") |
resultFields | array of test result field label/value pairs, e.g. @CustomField(name="My custom result field", value="Railflow rocks") |
caseType | name of the case type for a test in TestRail, e.g. Automated |
casePriority | name of the case priority for a test in TestRail, e.g. High |
jiraIds | array of Jira issue IDs, which will be set as refs in TestRail |
smartFailureAssignment | user email ID to assign failed test result to |
Code Example: Using the attributes above, the method level attributes can be applied to any of the tests methods.
package io.railflow.annotations;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.testng.Assert;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import io.railflow.annotations.testng.CurrentTest;
import io.railflow.annotations.testng.RailflowReporter;
@Listeners(value = { RailflowReporter.class })
public class RailflowDemo {
//method level annotation
@Railflow(title = "Railflow on the method level", jiraIds = {"ISSUE-44", "ISSUE-45"}, caseType = "Performance", casePriority = "High",
caseFields = { @CustomField(name = "required text field", value = "method value"), @CustomField(name = "estimate", value = "24s") },
resultFields = { @CustomField(name = "Custom field", value = "result from annotation on method")}, smartFailureAssignment = { "[email protected]"})
@Test
public void test() throws IOException {
CurrentTest.addAttachment("my log.txt", "something".getBytes(StandardCharsets.UTF_8));
}
@Test
public void test_failed() throws IOException {
CurrentTest.addAttachment("my log.txt", "something".getBytes(StandardCharsets.UTF_8));
Assert.fail("oops");
}
}
How Test Results Appear in TestRail
TESTNG_STEPS Mapping
The TESTNG_STEPS
option treats each test class
as a single testcase
. Methods inside the test class
are treated as test steps
within TestRail. This means that when results are exported to TestRail, each test class will be a separate test case in TestRail and each method inside the test class will be a test step in TestRail
Class Level
When TestNG classes use Railflow Class level attributes, the class level attributes are applied to the test results of methods inside the class.
Name | Description |
---|---|
title | name for the subsection which contains the test in TestRail, if not defined |
testrailIds | array of TestRail test IDs into which the result of this class will be added. |
caseFields | array of test case field label/value pairs, e.g. @CustomField(name="My custom case field", value="Railflow rocks") |
resultFields | array of test result field label/value pairs, e.g. @CustomField(name="My custom result field", value="Railflow rocks") |
caseType | name of the case type for a test in TestRail, e.g. Automated |
casePriority | name of the case priority for a test in TestRail, e.g. High |
jiraIds | array of Jira issue IDs, which will be set as refs in TestRail |
smartFailureAssignment | array of user email IDs, each failed test in the class will be assigned to one of these users in a round-robin fashion |
Example: Using the attributes above, these class level attributes will be passed to each of the test methods in the class.
package io.railflow.annotations.demo;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.testng.Assert;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import io.railflow.annotations.testng.CurrentTest;
import io.railflow.annotations.testng.RailflowReporter;
@Listeners(value = { RailflowReporter.class })
@Railflow(title = "Railflow on the class level", jiraIds = { "ISSUE-42", "ISSUE-43" }, caseType = "Automated", casePriority = "Critical",
caseFields = {@CustomField(name = "required text field", value = "class value"), @CustomField(name = "estimate", value = "42s") },
resultFields = {@CustomField(name = "Custom field", value = "result from class annotations")},
smartFailureAssignment = { "[email protected]", "[email protected]" })
public class RailflowDemo {
@Test
public void test() throws IOException {
CurrentTest.addAttachment("my log.txt", "something".getBytes(StandardCharsets.UTF_8));
}
@Test
public void test_failed() throws IOException {
CurrentTest.addAttachment("my log.txt", "something".getBytes(StandardCharsets.UTF_8));
Assert.fail("oops");
}
}
How Test Results Appear in TestRail
Method Level
Most of the annotations will not be applicable since TESTNG_STEPS means that each method is a test step in TestRail and these attributes are not applicable to a test steps.
Name | Description |
---|---|
title | test title, if not specified, test method name is used |
testrailIds | not applicable |
caseFields | not applicable |
resultFields | not applicable |
caseType | not applicable |
casePriority | not applicable |
jiraIds | not applicable |
smartFailureAssignment | not applicable |
Screenshots and attachments
When using TestNG with Selenium WebDriver, it can be very useful to take screenshots of the browser window when a test fails. Railflow provides utility classes and several static methods
for taking automatic screenshot so that they can also be uploaded to TestRail along with the failure exception message.
addAttachment(File attachmentFile)
: Adds arbitrary attachment file to the XML report.addAttachment(final String name, final InputStream inputStream)
: Adds an attachment file with given name and contents of inputStreamaddAttachment(final String name, final byte[] data)
: Adds an attachment file with given name and content specified by the given byte array
Railflow CLI / CI Plugins
The resulting railflow_report.xml
report file can be processed and the tests and test results uploaded to TestRail using Railflow CLI or CI plugins.
npx railflow -k ABCDE-12345-FGHIJ-67890 -url https://testrail.your-server.com/ -u testrail-username -p testrail-password -pr "Railflow Demo" -path Master/section1/section2 -f junit -r target/surefire-reports/railflow_report.xml
Jenkins plugin
TeamCity plugin
CLI Reference
Railflow CLI will automatically create tests, runs, plans, milestones, etc. if they do not exist.
Environment Variables:
To avoid exposing sensitive information like TestRail URL, License, username, and password in CLI arguments, users can set the following environment variables: RAILFLOW_LICENSE
, RAILFLOW_TR_URL
, RAILFLOW_TR_USER
, RAILFLOW_TR_PASSWORD
. Railflow CLI will always check these environment variables at run time.
Use double quotes for argument values with spaces. Example: --project "demo project"
Key | Required | Description | Example |
---|---|---|---|
-v, --version | No | Outputs Railflow version number | -v |
-k, --key | -k or -l | (online activation) License key. Can be set with RAILFLOW_LICENSE environment variable | -k XXXXX-XXXXX-XXXXX-XXXXX |
-l, --license-file | -k or -l | (offline activation) File path or remote url license file | -l /files/ActivationFile.skm |
-url, --url | Yes | TestRail instance URL. Can be set with RAILFLOW_TR_URL environment variable | -url https://example.testrail.io (opens in a new tab) |
-u, --username | Yes | TestRail username. Can be set with RAILFLOW_TR_USER environment variable | -u test-username |
-p, --password | Yes | TestRail password or API Key. Can be set with RAILFLOW_TR_PASSWORD environment variable | -p XtpHXiPLEODyhF |
-pr, --project | Yes | TestRail project name | -pr "example project" |
-path, --test-path | Yes | TestRail test cases path | -path "Section1/subsection2/ShoppingCart |
-f, --format | Yes | Report format: JUnit, JUnit-Steps, TestNg, TestNg-Steps, Cucumber, NUnit, NUnit-SpecFlow, Allure, Robot, TRX, xUnit, PyTest-Railflow, Playwright (case insensitive) | -f junit |
-r, --report-files | Yes | The file path(s) to the test report file(s) generated during the build. User can pass multiple values separated with spaces. Ant-style patterns such as **/surefire-reports/*.xml can be used. E.g. use target/surefire-reports/*.xml to capture all XML files in target/surefire-reports directory. | -r target/surefire-reports/*.xml target/failsafe-reports/*.xml |
-sm, --search-mode | Yes | Specifies the test case lookup algorithm. name: search for test case matching the name within the entire test suite. If test case found, update the test case. If test case not found, create a new test case within specified -path path: search for test case matching the name within the specified -path . If test case found, update the test case. If test case not found, create a new test case within specified -path | -sm path |
-px, --proxy | No | HTTP or SOCKS proxy configuration E.g. socks://username:[email protected]:1080 | -px socks://username:[email protected]:1080 |
-t, --timeout | No | Upload timeout (seconds) | -t 10 |
-tr, --test-run | No | TestRail test run name | -tr "Chrome Regression Run" |
-tp, --test-plan | No | TestRail test plan Name | -tp "Shopping Cart Test Plan" |
-mp, --milestone-path | No | TestRail milestone path | -mp Milestone1/Milestone2 |
-cf, --case-fields | No | TestRail test case custom fields. The format is [Field label]=[value] pairs, separated with space. E.g. "Case Field 1=value 1" "Case Field 2=value 2" ... | -cf "Case Field 1=value 1" "Case Field 2=value 2" |
-rf, --result-fields | No | TestRail test result custom fields. The format is [Field label]=[value] pairs, separated with space. E.g. "Result Field 1=value 1" "Result Field 2=value 2" ... | -rf "Result Field 1=value 1" "Result Field 2=value 2" |
-a, --assign | No | Smart Test Failure Assignment. Comma-separated list of TestRail users (email addresses). Railflow will assign failures based on a round robin algorithm. | -a [email protected],[email protected] |
-af, --assign-file | No | Smart Test Failure Assignment. File path containing list of TestRail users (email addresses). Note: One user per line | -af /assignees.txt |
-cn, --config-names | No | TestRail test plan configuration options. Configuration format is: [config_group_name]/[config_name]. E.g. "Operating Systems/Linux" "Browsers/Chrome" ... | -cn "Operating Systems/Linux" "Browsers/Chrome" |
-cr, --close-run | No | If Railflow should close the corresponding run after uploading test results | -cr |
-cp, --close-plan | No | If Railflow should close the corresponding plan after uploading test results | -cp |
-dg, --disable-grouping | No | If Railflow should ignore report structure and just upload all tests into a folder which is set by test-path parameter | -dg |
-tn, --template-name | No | The name of a template to use in TestRail. If it is not set, 'Test Case (Steps)' or the default one will be used | -tn "Test Case (Steps)" |
-cst, --case-type | No | The name of a type for cases | -cst other |
-csp, --case-priority | No | The name of a priority for cases | -csp medium |
-th, --thread-number | No | The number of concurrent threads for exporting data. Default is 4 | -th 8 |
-um, --upload-mode | No | Upload mode. Available values are: 0 (default) - create new test cases and do not overwrite existing ones; 1 - create new cases and overwrite existing ones; 2 - do not create new cases and overwrite existing ones; 3 - do not create new cases and do not overwrite existing ones | -um 1 |
-csf, --case-search-field | No | The name of the case field in TestRail which will be using for searching for existing test cases instead of test case title | -csf "Custom field" |
-ds, --disable-stats | No | If Railflow should disable collecting usage and error logs | -ds |
-fqtn, --fully-qualified-test-name | No | If checked, Railflow will use fully qualified test names from the report files for test names in TestRail | -fqtn |
-us, --untested-status | No | The name of the status to use in TestRail for untested/skipped tests | -us Skipped |
-ams, --attachment-max-size | No | Maximum size of an attachment. Can be set in Gb, Mb, Kb or b. If the unit is not provided considered as Mb. E.g. 1Gb, 2, 20Kb, 3Mb | -ams 1Gb |
-atw, --attachment-type-whitelist | No | The comma-separated list of file extensions which are allowed to upload. E.g. json, .html, .xml | -atw "json, .html, .xml" |
-atb, --attachment-type-blacklist | No | The comma-separated list of file extensions which are not allowed to upload. E.g. json, .html, .xml | -atb "json, .html, .xml" |
-nr, --no-run | No | Do not create or update Test Run in TestRail | -nr |
-tfn, --tags-field-name | No | The name of a test case field which will be holding tags from the report file if any. E.g. Cucumber Tags | -tfn "Cucumber Tags" |
-h, --help | No | Show the help information | -h |