To run this tool, you will need JRE 8. AdoptOpenJDK and Amazon Corretto are supported.
This project is based on Selenium, so you will a driver for a browser of your choice:
- For Firefox, download geckodriver.
- For Chrome/Chromium, download chromedriver.
A standalone cucumber-audit jar can be downloaded from releases.
You can also integrate this tool into an existing project. You will still need a driver for the browser.
The tests, or rather scenarios, are written in Gherkin. Thanks to it, no programming knowledge is needed to create a custom automated audit.
Multiple scenarios can be saved in a single feature files with a .feature
extension. There may be more than one
feature file used.
A sample feature file can look like the following:
Feature: Example Feature
Scenario: Secure Connection
Given app running on "https://httpbin.org" has already started
When I connect to "https://httpbin.org"
Then the connection should be secure
As it can be seen, the file has to start with Feature:
line containing the feature name. After that, the scenarios
can be defined.
The scenario has to start with Scenario:
and a scenario name. After that, the steps of the scenario can be defined.
The scenario consists of three stages:
- Given - a preparation stage, where the state of the environment before an action is defined.
- When - the action that is needed to trigger a feature or mechanism in application.
- Then - a verification stage, where the result is tested.
Keep in mind that the steps have to be defined in code in order to use them. This tool comes with handy predefined steps, which will be discussed later.
In this example, the Given stage checks whether the application is actually running. If it has not started yet or there is no connection, there is no point in auditing it.
Then, the desired action is the connection to the application. This When step triggers a HTTP connection that will be tested later.
The last step is a Then step that makes an assertion that the connection should be secure. It actually tests whether the connection is HTTPS and the certificate is trusted.
One stage can contain many steps. They can be joined by using the following words: And or But.
Feature: Example Feature
Scenario: An Expected Response
Given app running on "https://httpbin.org" has already started
And the response content is under inspection
When I go to "https://httpbin.org"
Then the response should contain "A simple HTTP Request & Response Service."
We can see that in the Given stages there are two steps. There were a preparation step added that enables the response content inspection.
Notice There is a major difference between I go to and I connect to. The first one opens the page in the browser, while the second is used only for protocol inspection.
After defining your first features, you can run them in the command line with cucumber-audit-standalone.
Given you have a gecko driver in /home/user/geckodriver
and the feature files in a /home/user/features
directory,
you can run the following command in a directory containing the cucumber-audit-standalone.jar
.
java -jar cucumber-audit-standalone.jar /home/user/features \
--glue io.github.multicatch.cucumber.audit \
--plugin pretty \
--webdriver.type GECKO \
--webdriver.gecko.driver /home/user/geckodriver
Given you have a gecko driver in C:\Users\user\geckodriver.exe
and the feature files in a C:\Users\user\features
directory,
you can run the following command in a directory containing the cucumber-audit-standalone.jar
.
java.exe -jar cucumber-audit-standalone.jar C:\\Users\\user\\features \
--glue io.github.multicatch.cucumber.audit \
--plugin pretty \
--webdriver.type GECKO \
--webdriver.gecko.driver C:\\Users\\user\\geckodriver.exe
To use a Chrome driver, you should switch webdriver.type
option to CHROME
.
The location of the chrome driver should also be specified with the webdriver.chrome.driver
option instead of webdriver.gecko.driver
.
Example:
java -jar cucumber-audit-standalone.jar /home/user/features \
--glue io.github.multicatch.cucumber.audit \
--plugin pretty \
--webdriver.type CHROME \
--webdriver.chrome.driver /home/user/chromedriver
Suppose you have a feature file named sample.feature
in /home/user/features
with the following content:
Feature: Example Feature
Scenario: An Expected Response
Given app running on "https://httpbin.org" has already started
And the response content is under inspection
When I go to "https://httpbin.org"
Then the response should contain "A simple HTTP Request & Response Service."
To run this feature only with a geckodriver, use the following command:
java -jar cucumber-audit-standalone.jar /home/user/features/sample.feature \
--glue io.github.multicatch.cucumber.audit \
--plugin pretty \
--webdriver.type GECKO \
--webdriver.gecko.driver /home/user/geckodriver
Jun 23, 2020 10:54:31 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
Scenario: An Expected Response # sample.feature:3
Given app running on "https://httpbin.org" has already started # io.github.multicatch.cucumber.audit.DiagnosticStepDefs.<init>(DiagnosticStepDefs.kt:14)
And the response content is under inspection # io.github.multicatch.cucumber.audit.ResponseInspectionStepDefs.<init>(ResponseInspectionStepDefs.kt:19)
When I go to "https://httpbin.org" # io.github.multicatch.cucumber.audit.NavigationStepDefs.<init>(NavigationStepDefs.kt:28)
Then the response should contain "A simple HTTP Request & Response Service." # io.github.multicatch.cucumber.audit.ResponseInspectionStepDefs.<init>(ResponseInspectionStepDefs.kt:67)
1 Scenarios (1 passed)
4 Steps (4 passed)
0m4,458s
There may be a need to hide the steps in the output of the above command. To do this, just remove --plugin pretty
from the command.
java -jar cucumber-audit-standalone.jar /home/user/features/sample.feature \
--glue io.github.multicatch.cucumber.audit \
--webdriver.type GECKO \
--webdriver.gecko.driver /home/user/geckodriver
You can also save the report to a json file by using --plugin json:report.json
.
Instead of a report.json
you can provide a custom file name, where the reports will be saved.
You can use a formatter to display the resulting file in a more readable format. There are plenty of tools that convert those reports to HTML files.
java -jar cucumber-audit-standalone.jar /home/user/features/sample.feature \
--glue io.github.multicatch.cucumber.audit \
--plugin json:report.json \
--webdriver.type GECKO \
--webdriver.gecko.driver /home/user/geckodriver
The json plugin can be used with a pretty plugin.
The browser may need to be run in a headless mode. In this mode, the window of the browser is not visible during testing.
To run in in a headless mode, add the --webdriver.headless true
option.
java -jar cucumber-audit-standalone.jar /home/user/features \
--glue io.github.multicatch.cucumber.audit \
--plugin pretty \
--webdriver.type GECKO \
--webdriver.gecko.driver /home/user/geckodriver \
--webdriver.headless true
You can also easily integrate it into any Java/Kotlin JVM project. To do this, add the following Maven dependency:
<dependency>
<groupId>io.github.multicatch</groupId>
<artifactId>cucumber-audit-context</artifactId>
<version>${cucumber.audit.version}</version>
<scope>test</scope>
</dependency>
Currently it only works with JUnit 4. You will also need an additional dependency:
<dependency>
<groupId>io.github.multicatch</groupId>
<artifactId>cucumber-audit-junit</artifactId>
<version>${cucumber.audit.version}</version>
<scope>test</scope>
</dependency>
You can then add a class that will run your features:
@RunWith(CucumberAudit.class)
@CucumberOptions(plugin = {
"pretty"
}, strict = true)
class CucumberAuditTest {
}
By default, Cucumber will look for features and step definitions in the same package as the configuration class.
Suppose you have defined the class in a package named com.example.audit
.
Cucumber will look for step definitions in com.example.audit
package, and will look for feature files in
com/example/audit
folder in your classpath (resources).
To configure the locations of features and step definitions, use features
and glue
fields in the @CucumberOptions
annotation.
You can create an AuditContext
instance to use a browser driver and manage proxy settings.
To do so, use the following method:
AuditContext context = AuditContextKt.auditContextOf(DriverType.GECKO, "location/of/driver", true);
The AuditContextKt.auditContextOf(DriverType, String, boolean)
method is used to create a class that
will manage the browser driver and the proxy. The first argument is the type of the browser driver,
the second argument is the location of the driver, and the third argument is used to specify whether to run
the browser in a headless mode.
Remember to define a teardown method that will stop the driver and kill the browser after the tests are done!
@RunWith(CucumberAudit.class)
@CucumberOptions(
plugin = {
"pretty"
},
glue = {
"io.github.multicatch.cucumber.audit"
},
strict = true
)
class CucumberAuditTest {
static AuditContext context = AuditContextKt.auditContextOf(DriverType.GECKO, "location/of/driver", true);
@AfterClass
public static void teardown() {
context.driver.quit();
}
}
To use predefined steps in your project, use the following Maven dependency:
<dependency>
<groupId>io.github.multicatch</groupId>
<artifactId>cucumber-audit-stepdefs</artifactId>
<version>${cucumber.audit.version}</version>
<scope>test</scope>
</dependency>
This will add standard cucumber-audit step definitions to your classpath.
You will need to specify the location of those definitions in a glue
option in @CucumberOptions
:
@RunWith(CucumberAudit.class)
@CucumberOptions(
plugin = {
"pretty"
},
glue = {
"io.github.multicatch.cucumber.audit"
},
strict = true
)
class CucumberAuditTest {
}
Notice These steps need an injected AuditContext. You will need to configure a dependency injection framework (like Guice) with Cucumber. See the Cucumber documentation for more info.
To configure Guice in your tests, first add the following dependencies:
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>7.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-guice</artifactId>
<version>7.13.0</version>
<scope>test</scope>
</dependency>
Then define the following configuration classes:
/**
* This class is used to configure Guice injection in Cucumber tests
*/
class GuiceInjectorSource implements InjectorSource {
@Override
public Injector getInjector() {
return Guice.createInjector(CucumberModules.createScenarioModule(), new CucumberTestModule());
}
}
/**
* This class is used to configure dependencies in Guice
*/
class CucumberTestModule extends AbstractModule {
public static final AuditContext AUDIT_CONTEXT = AuditContextKt.auditContextOf(DriverType.GECKO, "location/of/driver", true);
@Override
protected void configure() {
binder().bind(AuditContext.class).toInstance(AUDIT_CONTEXT);
}
}
GuiceInjectorSource should be in the packages that are scanned for glue. It is practically a glue class as seen by Cucumber.
Cucumber should automatically detect new InjectorSource and use it.
The tests should work now.