Supported Test Runners
Standalone mode (no 3rd party test-runner)
JUnit 4
- Import this maven dependency.
<dependency>
<groupId>io.fluentlenium</groupId>
<artifactId>fluentlenium-junit</artifactId>
<version>5.0.1</version>
<scope>test</scope>
</dependency>
- Extends FluentTest.
Fluent Test is the entry point of FluentLenium. You only have to extend FluentTest
and implement a test as usual.
public class MyTest extends FluentTest {
@Test
public void testGoogle() {
goTo("http://www.google.com");
}
}
If you need to make your tests run concurrently to speed them up, you should use dedicated libraries/extensions. You can use the Surefire maven plugin for example.
Surefire JUnit example
<profile>
<id>junit-tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<parallel>methods</parallel>
<threadCount>4</threadCount>
<forkCount>8</forkCount>
<reuseForks>true</reuseForks>
</configuration>
</plugin>
</plugins>
</build>
</profile>
More configuration examples can be found in
our Integration tests.
Enable them by activating framework-integration-tests
Maven profile.
JUnit 5 Jupiter
- Import this maven dependency.
<dependency>
<groupId>io.fluentlenium</groupId>
<artifactId>fluentlenium-junit-jupiter</artifactId>
<version>5.0.1</version>
<scope>test</scope>
</dependency>
- Extends FluentTest.
If you need to run your tests in parallel please take a look into
our Integration tests examples
.
Enable them by activating framework-integration-tests
Maven profile.
TestNG
- Import this maven dependency.
<dependency>
<groupId>io.fluentlenium</groupId>
<artifactId>fluentlenium-testng</artifactId>
<version>5.0.1</version>
<scope>test</scope>
</dependency>
- Extends FluentTestNG instead of FluentTest.
If you need to make your tests run concurrently to speed them up, you should use dedicated libraries/extensions. You can use the Surefire maven plugin for example.
Surefire TestNG example
<profile>
<id>testng-tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>test-suites/basic.xml</suiteXmlFile>
</suiteXmlFiles>
<goal>test</goal>
</configuration>
</plugin>
</plugins>
</build>
</profile>
TestNG test suite file
<suite name="Parallel tests" parallel="tests" thread-count="10">
<test name="Home Page Tests" parallel="methods" thread-count="10">
<parameter name="test-name" value="Home page"/>
<classes>
<class name="com.example.testng.OurLocationTest"/>
<class name="com.example.testng.OurStoryTest"/>
</classes>
</test>
<test name="Another Home Page Tests" parallel="classes" thread-count="2">
<parameter name="test-name" value="another home page"/>
<classes>
<class name="com.example.testng.HomeTest"/>
<class name="com.example.testng.JoinUsTest"/>
</classes>
</test>
</suite>
TestNG gives you more flexibility in order to the concurrency level, test suites and having better control on executed scenarios.
Both test frameworks are giving possibility to define the parallelism level of tests.
It is possible when you have multiple execution/concurrency levels set in your tests to face driver sharing issues,
so please use METHOD
driverLifecycle
configuration property when your execution methods are mixed up.
More configuration examples can be found in
our Integration tests.
Enable them by activating framework-integration-tests
Maven profile.
Cucumber
- Import this maven dependency.
<dependency>
<groupId>io.fluentlenium</groupId>
<artifactId>fluentlenium-cucumber</artifactId>
<version>4.4.1</version>
</dependency>
- Create runner class annotated with Cucumber.class
@RunWith(Cucumber.class)
@CucumberOptions
public class Runner {
}
- Extend
FluentCucumberTest
class in all of your steps classes:
public class ExampleSteps1 extends FluentCucumberTest {
}
public class ExampleSteps2 extends FluentCucumberTest {
}
or only in your BaseTest
class:
public class BaseTest extends FluentCucumberTest {
}
public class ExampleSteps1 extends BaseTest {
}
- Add
Before
andAfter
hooks:
import io.cucumber.java.Scenario;
import io.cucumber.java.After;
import io.cucumber.java.Before;
public class FluentHooks extends FluentCucumberTest {
@Before
public void beforeScenario(Scenario scenario) {
before(scenario);
}
@After
public void afterScenario(Scenario scenario) {
after(scenario);
}
}
Hooks can be added like this:
public class FluentHooks extends FluentCucumberTest {
public FluentHooks() {
Before(this::before);
After(this::after);
}
}
Notes related to Cucumber hooks:
1) Hooks should be added ONCE for your tests. Do not add these hooks in all your steps classes.
2) Adding these hooks starts FluentLenium context during execution of scenario. It means that driver will start automatically. If you want to start WebDriver only for some scenarios, you can use tagged Cucumber hooks, for example:
@fluent
Scenario: Driver should start when tag is present above scenario
Then WebDriver starts as expected
and add tags to your hooks:
@Before({"@fluent"})
public void beforeScenario(Scenario scenario){
before(scenario);
}
@After({"@fluent"})
public void afterScenario(Scenario scenario){
after(scenario);
}
3) Hooks in Cucumber
cannot be extended. So do not add Before
and After
hooks in BaseTest
(if you use such
pattern) but add them in any other class:
public class FluentHooks extends BaseTest {
@Before
public void beforeScenario(Scenario scenario) {
before(scenario);
}
@After
public void afterScenario(Scenario scenario) {
after(scenario);
}
}
- It is possible to access current
FluentCucumberTest
context using syntax:
FluentTestContainer.FLUENT_TEST.instance()
It can be handy if you want to have access to the current WebDriver instance. The purpose of FluentTestContainer
is to
share
state between many steps classes.
- Keep your configuration in
BaseTest
:
// example configuration
@FluentConfiguration(webDriver = "chrome")
public class BaseTest extends FluentCucumberTest {
@Override
public Capabilities getCapabilities() {
return new ChromeOptions();
}
}
or class with Cucumber hooks:
// example configuration
@FluentConfiguration(webDriver = "chrome")
public class FluentHooks extends FluentCucumberTest {
@Override
public Capabilities getCapabilities() {
return new ChromeOptions();
}
@Before
public void beforeScenario(Scenario scenario) {
before(scenario);
}
@After
public void afterScenario(Scenario scenario) {
after(scenario);
}
}
- By default, a new instance of WebDriver is created for each scenario. If you want to run single WebDriver for all scenarios in feature, change DriverLifecycle to JVM level:
import io.fluentlenium.adapter.cucumber.FluentCucumberTest;
import io.fluentlenium.configuration.ConfigurationProperties;
import io.fluentlenium.configuration.FluentConfiguration;
@FluentConfiguration(webDriver = "chrome", driverLifecycle = ConfigurationProperties.DriverLifecycle.JVM)
public class BaseTest extends FluentCucumberTest {
}
- Remember, that page objects still need to inherit
FluentPage
to run correctly.
E2E Cucumber tests are present
in Cucumber example.
Enable it by activating examples
Maven profile.
- Until FLuentLenium 4.3.1, both
cucumber.api
andio.cucumber
based classes (@Given
,@When
,@CucumberOptions
, etc.) are supported, however theFluentCucumberTest
based tests still use the old CucumberObjectFactory
due to the Cucumber limitation of allowing only one instance ofObjectFactory
to be used, and also to provide backward compatibility for projects where Cucumber version cannot be upgraded. - From FluentLenium 4.4.1 on support for
cucumber.api
package based Before and After hooks is removed. Onlyio.cucumber
packages are supported.
Spock
- Import this maven dependency.
<dependency>
<groupId>io.fluentlenium</groupId>
<artifactId>fluentlenium-spock</artifactId>
<version>5.0.1</version>
<scope>test</scope>
</dependency>
- Extends FluentSpecification instead of FluentTest.
E2E Spock tests are present in Spock example
.
Enable it by activating examples
Maven profile.
Spring TestNG
- Import this maven dependency.
<dependency>
<groupId>io.fluentlenium</groupId>
<artifactId>fluentlenium-spring-testng</artifactId>
<version>5.0.1</version>
<scope>test</scope>
</dependency>
- Extends FluentTestNgSpringTest instead of FluentTest.
E2E Spring testNG tests are present
in Spring example.
Enable it by activating examples
Maven profile.
Kotest
- Import this dependency:
Maven
<dependency>
<groupId>io.fluentlenium</groupId>
<artifactId>fluentlenium-kotest</artifactId>
<version>5.0.1</version>
<scope>test</scope>
</dependency>
Gradle
testImplementation("io.fluentlenium:fluentlenium-kotest:5.0.1")
- There are baseclasses available for all Kotest testing styles. Choose one and extend your test from it:
class ExampleStringSpec : FluentStringSpec({
"Title should be correct" {
goTo(URL)
}
})
Check src for examples.
There is an example setup available in Kotest example.
Standalone mode
If you want to use FluentLenium as a pure automation Framework, without any testing framework adapter,
you can create an instance of FluentStandalone
and use it directly, or extend FluentStandaloneRunnable
and
implement doRun()
method.
FluentStandalone
Create an instance of FluentStandalone
and use it directly. You have to manually invoke init()
to initialize the
WebDriver, and quit()
to close it.
FluentStandalone standalone=new FluentStandalone()
standalone.init();
standalone.goTo(DEFAULT_URL);
standalone.await().atMost(1,SECONDS).until(test.$(".fluent",with("name").equalTo("name"))).present();
standalone.el("input").enabled();
standalone.quit();
Using a FluentStandalone
instance is quite verbose because of the need to repeat the instance name before each
instruction. If it’s a problem for you, you should consider extending FluentStandaloneRunnable
.
FluentStandaloneRunnable
Another option is to extend FluentStandaloneRunnable
, implement doRun()
method and invoke run()
method on an
instance of this class. Fluent WebDriver is initialized before and released after run()
method invocation.
public class MyStandaloneRunnable extends FluentStandaloneRunnable {
@Override
protected void doRun() {
goTo(DEFAULT_URL);
await().atMost(1, SECONDS).until(test.$(".fluent", with("name").equalTo("name"))).present();
el("input").enabled();
}
}
MyStandaloneRunnable runnable=new MyStandaloneRunnable();
runnable.run();