Skip to content

Commit

Permalink
Add docs for Configuration feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Toilal committed Aug 22, 2016
1 parent 9d7b001 commit 8357c20
Show file tree
Hide file tree
Showing 44 changed files with 666 additions and 289 deletions.
223 changes: 166 additions & 57 deletions README.md
Expand Up @@ -7,7 +7,7 @@
FluentLenium is a framework that helps you write [Selenium](http://seleniumhq.org/) tests. FluentLenium is a framework that helps you write [Selenium](http://seleniumhq.org/) tests.
FluentLenium provides a [fluent interface](http://en.wikipedia.org/wiki/Fluent_interface) to the [Selenium Web Driver](http://seleniumhq.org/docs/03_webdriver.html). FluentLenium provides a [fluent interface](http://en.wikipedia.org/wiki/Fluent_interface) to the [Selenium Web Driver](http://seleniumhq.org/docs/03_webdriver.html).
FluentLenium lets you use the assertion framework you like, either [JUnit assertions](http://www.junit.org/apidocs/org/junit/Assert.html), [Hamcrest](http://code.google.com/p/hamcrest/wiki/Tutorial) FluentLenium lets you use the assertion framework you like, either [JUnit assertions](http://www.junit.org/apidocs/org/junit/Assert.html), [Hamcrest](http://code.google.com/p/hamcrest/wiki/Tutorial)
or [AssertJ](https://github.com/joel-costigliola/assertj-core) (old one: ~~[Fest-assert](https://github.com/alexruiz/fest-assert-2.x/wiki)~~). or [AssertJ](https://github.com/joel-costigliola/assertj-core).




# 5 second example # 5 second example
Expand Down Expand Up @@ -753,56 +753,180 @@ If you want to test concurrency or if you need for any reason to not use the mec
``` ```




## Configure FluentLenium


## Customize FluentLenium FluentLenium can be configured in many ways through configuration properties.


### Driver ### Configuration properties
If you need to change your driver, just override the `getDefaultDriver` method in your test. You can use every driver.
For instance, to run your tests on [BrowserStack](https://browserstack.com)


```java - **configurationFactory**
@Override
public WebDriver getDefaultDriver() { Set this to a class implementing ```ConfigurationFactory``` to customize the ways properties are read.
String HUB_URL = "http://" + USERNAME + ":" + ACCESS_KEY + "@hub.browserstack.com/wd/hub"; This allow to configure properties from sources that are not supported by default FluentLenium.

Default value: ```org.fluentlenium.configuration.DefaultConfigurationFactory```.

- **webDriver**

Set this property to a value supported by ```WebDrivers``` registry.


DesiredCapabilities caps = new DesiredCapabilities(); Default value: ```firefox```.
caps.setCapability("os", "OS X");
caps.setCapability("os_version", "El Capitan"); Possible values are ```firefox```, ```chrome```, ```ie``` and ```htmlunit```, or any class name implementing ```WebDriver```.
caps.setCapability("browser", "firefox");
caps.setCapability("browser_version", "44");
caps.setCapability("build", "Sample FluentLenium Tests");
caps.setCapability("browserstack.debug", "true");


URL hubURL = null; - **baseUrl**
try {
hubURL = new URL(HUB_URL); Sets the base URL used to build absolute URL when relative URL is given to {@link FluentAdapter#goTo(String)}.
} catch(Exception e) {
System.out.println("Please provide proper credentials. Error " + e); Default value: ```null```.
}


return new RemoteWebDriver(hubURL, caps); - **pageLoadTimeout**
}
``` Sets the amount of time to wait for a page load to complete before throwing an error.
If the timeout is negative, page loads can be indefinite.

Default value: ```null```.


### Base Url - **implicitlyWait**
If you want to defined a default base url, just override the `getDefaultBaseUrl` method in your test. Every page created with @Inject will also use this variable.
If a base url is provided, the current url will be relative to that base url. Specifies the amount of time the driver should wait when searching for an element if it is
not immediately present.

Default value: ```null```.


- **scriptTimeout**

Sets the amount of time to wait for an asynchronous script to finish execution before
throwing an error. If the timeout is negative, then the script will be allowed to run
indefinitely.

Default value: ```null```.

- **screenshotPath**

Sets the filesystem path where screenshot will be saved when calling {@link FluentAdapter#takeScreenShot()} or
{@link FluentAdapter#takeScreenShot(String)}.

Default value: ```null```.


- **screenshotMode**

Sets the trigger mode of screenshots. Can be ```ON_AUTOMATIC_ON_FAIL``` to take screenshot when the test fail
or ```MANUAL```.

Default value: ```null```.


### TimeOut
To set the time to wait when searching an element, you can use in your test:
```java
withDefaultSearchWait(long l, TimeUnit timeUnit);
```


To set the time to wait when loading a page, you can use: - **htmlDumpPath**

Sets the filesystem path where screenshot will be saved.

Default value: ```null```.


- **htmlDumpMode**

Sets the trigger mode of html dump. Can be ```ON_AUTOMATIC_ON_FAIL``` to take html dump when the test fail
or ```MANUAL```.

Default value: ```null```.

Keep in mind that when those properties are defined through System Properties or Environment Variables, they need to
be prefixed with ```fluentlenium.``` (ie. ```fluentlenium.webDriver=chrome```).

### Configuration Ways

It's possible to define those properties using:

- **Overrides** of JavaBean **property getters** of the test class.

public class SomeFluentTest extends FluentTest {
@Override
public String getWebDriver() {
return "chrome";
}
}

- **Calls** of JavaBean **property setters** of the test class.

public class SomeFluentTest extends FluentTest {
public SomeFluentTest() {
setWebDriver("chrome");
}
}

- **System properties** of the Java Environment, passed using ```-D``` on the command line. Property names must be **prefixed with fluentlenium.**.

mvn clean test -Dfluentlenium.webDriver=chrome

- **Environment Variable** of the Operating System. Property names **must be prefixed with fluentlenium.**.

$ EXPORT fluentlenium.webDriver=chrome; mvn clean test;


- **@FluentConfiguration Annotation** on test class to configure.

@FluentConfiguration(webDriver="chrome")
public class SomeFluentTest extends FluentTest {
....
}


- **Java Properties file** located at ```/fluentlenium.properties``` in the classpath.

$ cat fluentlenium.properties
webDriver=chrome
...

This list of way to configure fluentlenium is ordered by priority. If a value is defined for a property in an element,
lower ways will just be ignored.

You may implement additionnal ways to read configuration property by implementing another
```ConfigurationFactory``` and set the new configuration factory class name in the ```configurationFactory``` property.

### Driver consideration
You can register a custom WebDriver type by providing your own implementation of ```WebDriverFactory``` in
```WebDrivers``` registry.

A ```WebDriverFactory``` implementation is responsible for creating new instances for a type of WebDriver.

For instance, to run your tests on [BrowserStack](https://browserstack.com)

```java ```java
withDefaultPageWait(long l, TimeUnit timeUnit); public class BrowserStackWebDriverFactory implements WebDriverFactory {
``` @Override
public WebDriver newWebDriver() {
String HUB_URL = "http://" + USERNAME + ":" + ACCESS_KEY + "@hub.browserstack.com/wd/hub";

DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability("os", "OS X");
caps.setCapability("os_version", "El Capitan");
caps.setCapability("browser", "firefox");
caps.setCapability("browser_version", "44");
caps.setCapability("build", "Sample FluentLenium Tests");
caps.setCapability("browserstack.debug", "true");

URL hubURL = null;
try {
hubURL = new URL(HUB_URL);
} catch(Exception e) {
System.out.println("Please provide proper credentials. Error " + e);
}

return new RemoteWebDriver(hubURL, caps);
}


Be aware that when you modified this elements, the webDriver instance will be modified so your page will also be affected. @Override
public String[] getNames() {
return new String[0];
}
}
```


### Configuration Instead of implementing a new ```WebDriverFactory``` class, you may also override ```newWebDriver()``` in the Test
Override the getDefaultDriver method and use the selenium way to configure your driver. class, but doing so will ignore any value defined in ```webDriver``` configuration property.


## Browser Lifecycle ## Browser Lifecycle
For JUnit and TestNG, you can define the browser lifecycle. For JUnit and TestNG, you can define the browser lifecycle.
Expand Down Expand Up @@ -985,10 +1109,10 @@ Then use ```SNAPSHOT``` version when declaring the dependencies.
</dependency> </dependency>
``` ```


## FluentLenium and other frameworks ## FluentLenium Assertions


### jUnit ### JUnit
FluentLenium uses jUnit by default. You can use test using [jUnit](http://www.junit.org) assertions, but can of course use others frameworks such as [AssertJ](https://github.com/joel-costigliola/assertj-core) or [Hamcrest](http://code.google.com/p/hamcrest/). FluentLenium uses JUnit by default. You can use test using [JUnit](http://www.junit.org) assertions, but can of course use others frameworks such as [AssertJ](https://github.com/joel-costigliola/assertj-core) or [Hamcrest](http://code.google.com/p/hamcrest/).


```java ```java
goTo("http://mywebpage/"); goTo("http://mywebpage/");
Expand All @@ -997,9 +1121,6 @@ $("#create-button").click();
assertEqual("Hello toto",title()); assertEqual("Hello toto",title());
``` ```


### Fest-Assert
Fest-Assert is now deprecated. This lib is no longer maintained. Consider switching to AssertJ

### AssertJ ### AssertJ
```java ```java
goTo("http://mywebpage/"); goTo("http://mywebpage/");
Expand All @@ -1022,15 +1143,3 @@ $("#firstName").fill().with("toto");
$("#create-button").click(); $("#create-button").click();
assertThat(title(),equalTo("Hello toto")); assertThat(title(),equalTo("Hello toto"));
``` ```
##Resources

In English:

- [Play2 and FluentLenium screencast](http://www.youtube.com/watch?v=diVhWRtJuxU) and the associated [code] (http://ics-software-engineering.github.io/play-example-fluentlenium/)

In French:

- [SlideShare](http://www.slideshare.net/MathildeLemee/fluentlenium)
- [Cucumber and FluentLenium - more to come](http://blog.jetoile.fr/2013/04/fluentlenium-et-cucumber-jvm-complement.html)

Please contact us on the mailing list if you want your post to be added to that list !
Expand Up @@ -2,6 +2,9 @@


import org.fluentlenium.core.FluentDriver; import org.fluentlenium.core.FluentDriver;


/**
* Default {@link DriverContainer} implementation, using a simple variable to store the {@link FluentDriver} instance.
*/
public class DefaultDriverContainer implements DriverContainer { public class DefaultDriverContainer implements DriverContainer {
private FluentDriver driver; private FluentDriver driver;


Expand Down
Expand Up @@ -4,7 +4,7 @@
import org.fluentlenium.core.FluentDriverProvider; import org.fluentlenium.core.FluentDriverProvider;


/** /**
* Container for FluentDriver of the actual test. * Container for {@link FluentDriver} of the actual test adapter.
*/ */
public interface DriverContainer extends FluentDriverProvider { public interface DriverContainer extends FluentDriverProvider {
/** /**
Expand Down
Expand Up @@ -3,13 +3,16 @@
import lombok.experimental.Delegate; import lombok.experimental.Delegate;
import org.fluentlenium.configuration.Configuration; import org.fluentlenium.configuration.Configuration;
import org.fluentlenium.configuration.ConfigurationFactoryProvider; import org.fluentlenium.configuration.ConfigurationFactoryProvider;
import org.fluentlenium.configuration.ConfigurationRead; import org.fluentlenium.configuration.ConfigurationProperties;
import org.fluentlenium.configuration.WebDrivers; import org.fluentlenium.configuration.WebDrivers;
import org.fluentlenium.core.FluentDriver; import org.fluentlenium.core.FluentDriver;
import org.fluentlenium.core.FluentDriverControl; import org.fluentlenium.core.FluentDriverControl;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;


public class FluentAdapter implements FluentDriverControl, ConfigurationRead { /**
* Generic adapter to {@link FluentDriver}.
*/
public class FluentAdapter implements FluentDriverControl, ConfigurationProperties {


private final DriverContainer driverContainer; private final DriverContainer driverContainer;


Expand All @@ -32,7 +35,7 @@ public FluentAdapter(DriverContainer driverContainer, WebDriver webDriver) {
initFluent(webDriver); initFluent(webDriver);
} }


@Delegate(types = ConfigurationRead.class) @Delegate(types = ConfigurationProperties.class)
public Configuration getConfiguration() { public Configuration getConfiguration() {
return configuration; return configuration;
} }
Expand All @@ -57,6 +60,8 @@ protected DriverContainer getDriverContainer() {
/** /**
* Load a {@link WebDriver} into this adapter. * Load a {@link WebDriver} into this adapter.
* *
* This method should not be called by end user.
*
* @param webDriver webDriver to use. * @param webDriver webDriver to use.
* @return adapter * @return adapter
* @throws IllegalStateException when trying to register a different webDriver that the current one. * @throws IllegalStateException when trying to register a different webDriver that the current one.
Expand Down Expand Up @@ -84,6 +89,8 @@ public void initFluent(WebDriver webDriver) {


/** /**
* Release the current {@link WebDriver} from this adapter. * Release the current {@link WebDriver} from this adapter.
*
* This method should not be called by end user.
*/ */
public void releaseFluent() { public void releaseFluent() {
if (getFluentDriver() != null) { if (getFluentDriver() != null) {
Expand All @@ -95,14 +102,23 @@ public void releaseFluent() {
/** /**
* @return A new WebDriver instance. * @return A new WebDriver instance.
* @see #getDriver() * @see #getDriver()
* @deprecated Override {@link #newWebDriver()} instead, or consider using {@link #getDriver()} and #ConfigurationRead{@link #getDriver()} * @deprecated Override {@link #newWebDriver()} instead, or consider using {@link ConfigurationProperties#getWebDriver()}.
*/ */
@Deprecated @Deprecated
public WebDriver getDefaultDriver() { public WebDriver getDefaultDriver() {
return WebDrivers.INSTANCE.newWebDriver(getWebDriver()); return WebDrivers.INSTANCE.newWebDriver(getWebDriver());
} }


/** /**
* Creates a new {@link WebDriver} instance.
*
* This method should not be called by end user, but may be overriden if required.
*
* Before overriding this method, you should consider using {@link WebDrivers} registry and configuration
* {@link ConfigurationProperties#getWebDriver()}.
*
* To retrieve the current managed {@link WebDriver}, call {@link #getDriver()} instead.
*
* @return A new WebDriver instance. * @return A new WebDriver instance.
* @see #getDriver() * @see #getDriver()
*/ */
Expand Down
Expand Up @@ -7,7 +7,9 @@
import org.junit.runners.model.Statement; import org.junit.runners.model.Statement;


/** /**
* All Junit Test should extends this class. It provides default parameters. * JUnit FluentLenium Test Adapter.
*
* Extends this class to provide FluentLenium support to your JUnit Test class.
*/ */
public abstract class FluentTest extends FluentTestRunnerAdapter { public abstract class FluentTest extends FluentTestRunnerAdapter {
public FluentTest() { public FluentTest() {
Expand Down
Expand Up @@ -11,7 +11,7 @@
import java.util.List; import java.util.List;


/** /**
* Adapter used by any class based Test Runners adapters. * Generic Test Runner Adapter to FluentDriver.
*/ */
public class FluentTestRunnerAdapter extends FluentAdapter { public class FluentTestRunnerAdapter extends FluentAdapter {
private final SharedDriverStrategyReader sdsr; private final SharedDriverStrategyReader sdsr;
Expand Down Expand Up @@ -201,10 +201,10 @@ protected void failed(Class<?> testClass, String testName) {
*/ */
protected void failed(Throwable e, Class<?> testClass, String testName) { protected void failed(Throwable e, Class<?> testClass, String testName) {
if (isFluentDriverAvailable()) { if (isFluentDriverAvailable()) {
if (getScreenshotMode() == TriggerMode.ON_FAIL && canTakeScreenShot()) { if (getScreenshotMode() == TriggerMode.AUTOMATIC_ON_FAIL && canTakeScreenShot()) {
takeScreenShot(testClass.getSimpleName() + "_" + testName + ".png"); takeScreenShot(testClass.getSimpleName() + "_" + testName + ".png");
} }
if (getHtmlDumpMode() == TriggerMode.ON_FAIL && getDriver() != null) { if (getHtmlDumpMode() == TriggerMode.AUTOMATIC_ON_FAIL && getDriver() != null) {
takeHtmlDump(testClass.getSimpleName() + "_" + testName + ".html"); takeHtmlDump(testClass.getSimpleName() + "_" + testName + ".html");
} }
} }
Expand Down
Expand Up @@ -6,6 +6,8 @@
* Instead of extending FluentTest, you can instantiate this class directly. * Instead of extending FluentTest, you can instantiate this class directly.
* <p> * <p>
* If you want to test concurrency, or if you need for any reason to not use JUnit nor TestNG, you may use this class. * If you want to test concurrency, or if you need for any reason to not use JUnit nor TestNG, you may use this class.
* <p>
* You should call {@link #releaseFluent()} manually to close the underlying webdriver.
*/ */
public class IsolatedTest extends FluentAdapter { public class IsolatedTest extends FluentAdapter {


Expand Down

0 comments on commit 8357c20

Please sign in to comment.