├── .github
└── allure-img.png
├── .gitignore
├── .travis.yml
├── MIT-LICENSE.txt
├── README.md
├── driver
├── linux
│ ├── chromedriver
│ └── geckodriver
├── osx
│ ├── chromedriver
│ └── geckodriver
└── windows
│ ├── chromedriver.exe
│ └── geckodriver.exe
├── pom.xml
├── src
├── main
│ ├── java
│ │ └── selenium
│ │ │ ├── appDomain
│ │ │ └── AppDomain.java
│ │ │ ├── config
│ │ │ └── DomainConfiguration.java
│ │ │ ├── driver
│ │ │ ├── Driver.java
│ │ │ └── DriverManager.java
│ │ │ ├── localization
│ │ │ └── LocaleText.java
│ │ │ └── pageobject
│ │ │ ├── HomePage.java
│ │ │ └── LoginPage.java
│ └── resources
│ │ └── locale_en.properties
└── test
│ ├── java
│ └── selenium
│ │ ├── Application.java
│ │ ├── context
│ │ └── Base.java
│ │ ├── listeners
│ │ └── WebDriverListener.java
│ │ ├── testdata
│ │ ├── file
│ │ │ └── FileLoaderService.java
│ │ └── properties
│ │ │ └── User.java
│ │ └── tests
│ │ └── SimpleTestExamples.java
│ └── resources
│ ├── application-release.properties
│ ├── application.properties
│ └── testdata
│ └── user
│ └── user_com.json
└── testng.xml
/.github/allure-img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edinc/java-selenium-framework/fd31c15b7456a64c2b95792bdf3dc7af1a09ca13/.github/allure-img.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | *.iml
3 | *.DS_Store
4 | velocity.log
5 | target
6 | test-output
7 | allure-results
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | os: osx
2 | language: java
3 | sudo: required
4 |
5 | env:
6 | - MOZ_HEADLESS=1
7 | addons:
8 | firefox: latest
9 |
10 | script:
11 | - mvn clean test -Dspring.profiles.active=live -Dcountry=com -Dbrowser=firefox -Dmode=headless
12 |
13 | notifications:
14 | slack: tehnografija:yGLRFooashh7wutsGmMQFxou
--------------------------------------------------------------------------------
/MIT-LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018 Edin Cenanovic
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Java Selenium Framework [](https://travis-ci.org/edinc/java-selenium-framework)
2 |
3 | The Selenium Java Framework is a good starting point for writing your UI automated tests utilizing Java,
4 | Selenium and Zalenium for running the tests in a CI manner.
5 |
6 | ## Features
7 | ### Multiple domains
8 | Tests can be configured to run against different domains. For example:
9 | https://www.some-site.de and https://www.some-site.fr.
10 |
11 | ### Multiple environments
12 | Similar as for multiple domains the tests can also be run on multiple environments,
13 | for example a staging and a live environment. It is as simple as changing a spring profile parameter.
14 |
15 | ### Localization
16 | Page content can be validated with different languages through a config file.
17 |
18 | ### User data handling
19 | Handling user data within a json file where the appropriate user will be determined by country.
20 |
21 | ### Headless
22 | The option to run the tests in headless mode (without opening a browser).
23 |
24 | ### Zalenium integration
25 | [Zalenium](https://github.com/zalando/zalenium) is a Selenium Grid extension to scale your local grid dynamically with docker containers.
26 |
27 | ### Allure reports integration
28 | [Allure Framework](https://github.com/allure-framework/allure2) is a flexible lightweight multi-language test report tool that shows a very concise representation of what has been tested in a neat web report form
29 |
30 | ### Parallelization
31 | The framework has the ability to run multiple tests in parallel. Setting this up just requires to set the `thread-count` paramenter in `testng.xml`.
32 |
33 | ## Tech Stack
34 | * Java 8
35 | * Maven
36 | * Spring Boot
37 | * TestNG
38 | * Allure
39 | * Zalenium
40 |
41 | ## How-to
42 | ### Local on different browsers
43 | To run the tests on your local machine use the command:
44 |
45 | ```
46 | mvn clean test -Dspring.profiles.active=live -Dcountry=com -Dbrowser=chrome
47 | ```
48 |
49 | The parameters explained:
50 | * `spring.profiles.active` - defines on which environment the tests will run
51 | * `country` - defines on which domain the tests will run
52 | * `browser` - defines the browser (`chrome/firefox`)
53 |
54 |
55 | ### With Zalenium
56 | To be able to run the tests on Zalenium (which is basically just a dockerized Selenium Grid), first Zalenium has to be started.
57 | ```
58 | # Pull docker-selenium
59 | docker pull elgalu/selenium
60 |
61 | # Pull Zalenium
62 | docker pull dosel/zalenium
63 |
64 | docker run --rm -ti --name zalenium -p 4444:4444 \
65 | -v /var/run/docker.sock:/var/run/docker.sock \
66 | -v /tmp/videos:/home/seluser/videos \
67 | --privileged dosel/zalenium start
68 | ```
69 |
70 | After Zalenium is running just the browser parameter has to be changed in order to run the tests
71 |
72 | ```
73 | mvn clean test -Dspring.profiles.active=live -Dcountry=com -Dbrowser=zalenium
74 | ```
75 |
76 | ### Headless
77 | The latest versions of the Chrome and Firefox browsers have the feature to run browsers in headless mode. This speeds up the running time of the tests immensely. For running the tests using the headlless mode feature:
78 |
79 | ```
80 | mvn clean test -Dspring.profiles.active=live -Dcountry=com -Dbrowser=chrome -Dmode=headless
81 | ```
82 |
83 | where as browser either `chrome` or `firefox` can be selected.
84 |
85 | ### Running the tests on a different OS
86 | Currently the tests are configured to run just on MacOS. But this can be changed [here](https://github.com/edinc/java-selenium-framework/blob/master/src/main/java/selenium/driver/DriverManager.java#L21) , the relative path just has to be replaced with the appropriate driver for that OS.
87 |
88 | ## Reports
89 |
90 | Reporting of the tests results is one of the most important aspects of a framework. It doesn't matter how many and good your tests are when they are not enough visible. In this framework Allure was used to generate
91 | visually rich and insightful reports.
92 |
93 | 
94 |
95 | Allure has to be installed before being able to show test results:
96 |
97 | ```
98 | $ brew untap qameta/allure
99 | $ brew update
100 | $ brew install allure
101 | ```
102 |
103 | After every test run the results are automatically stored in an `allure-results` directory. The results then can be seen locally by running:
104 |
105 | ```
106 | allure serve
107 | ```
108 |
109 | or in all popular CI's with the help of allure plugins.
110 | ## Contact
111 |
112 | Open a github issue or for suggestions a Pull Request straight away.
--------------------------------------------------------------------------------
/driver/linux/chromedriver:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edinc/java-selenium-framework/fd31c15b7456a64c2b95792bdf3dc7af1a09ca13/driver/linux/chromedriver
--------------------------------------------------------------------------------
/driver/linux/geckodriver:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edinc/java-selenium-framework/fd31c15b7456a64c2b95792bdf3dc7af1a09ca13/driver/linux/geckodriver
--------------------------------------------------------------------------------
/driver/osx/chromedriver:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edinc/java-selenium-framework/fd31c15b7456a64c2b95792bdf3dc7af1a09ca13/driver/osx/chromedriver
--------------------------------------------------------------------------------
/driver/osx/geckodriver:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edinc/java-selenium-framework/fd31c15b7456a64c2b95792bdf3dc7af1a09ca13/driver/osx/geckodriver
--------------------------------------------------------------------------------
/driver/windows/chromedriver.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edinc/java-selenium-framework/fd31c15b7456a64c2b95792bdf3dc7af1a09ca13/driver/windows/chromedriver.exe
--------------------------------------------------------------------------------
/driver/windows/geckodriver.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/edinc/java-selenium-framework/fd31c15b7456a64c2b95792bdf3dc7af1a09ca13/driver/windows/geckodriver.exe
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | testng.xml
9 | 1.8.12
10 |
11 |
12 | java.selenium
13 | java-selenium-framework
14 | 1.0-SNAPSHOT
15 |
16 |
17 |
18 | edinc
19 | Edin Cenanovic
20 | cenanovice@gmail.com
21 |
22 |
23 |
24 |
25 |
26 | org.seleniumhq.selenium
27 | selenium-java
28 | 3.12.0
29 |
30 |
31 | org.hamcrest
32 | hamcrest-all
33 | 1.3
34 | test
35 |
36 |
37 | com.saucelabs
38 | saucerest
39 | 1.0.35
40 |
41 |
42 | org.testng
43 | testng
44 | 6.11
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-starter
49 | 1.3.1.RELEASE
50 |
51 |
52 | org.springframework
53 | spring-web
54 | 4.2.4.RELEASE
55 |
56 |
57 | org.springframework
58 | spring-test
59 | 4.2.4.RELEASE
60 |
61 |
62 | io.qameta.allure
63 | allure-testng
64 | 2.0-BETA19
65 | test
66 |
67 |
68 | org.apache.commons
69 | commons-lang3
70 | 3.4
71 |
72 |
73 | com.fasterxml.jackson.core
74 | jackson-databind
75 | 2.9.10.3
76 | test
77 |
78 |
79 |
80 |
81 |
82 |
83 | org.apache.maven.plugins
84 | maven-surefire-plugin
85 | 2.20.1
86 |
87 |
88 | ${suiteXmlFile}
89 |
90 |
91 | -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
92 |
93 |
94 |
95 | usedefaultlisteners
96 | false
97 |
98 |
99 |
100 |
101 |
102 | org.aspectj
103 | aspectjweaver
104 | ${aspectj.version}
105 |
106 |
107 |
108 |
109 | org.apache.maven.plugins
110 | maven-compiler-plugin
111 | 3.1
112 |
113 | javac-with-errorprone
114 | true
115 | utf-8
116 | 1.8
117 | 1.8
118 |
119 |
120 |
121 | org.codehaus.plexus
122 | plexus-compiler-javac-errorprone
123 | 2.5
124 |
125 |
126 |
127 |
128 |
129 |
130 | src/main/resources
131 |
132 |
133 | src/test/resources
134 |
135 |
136 | src/main/java
137 |
138 | **/*.java
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 | io.qameta.allure
148 | allure-maven
149 | 2.8
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/src/main/java/selenium/appDomain/AppDomain.java:
--------------------------------------------------------------------------------
1 | package selenium.appDomain;
2 |
3 | import org.apache.commons.lang3.builder.ToStringBuilder;
4 |
5 | import java.util.Locale;
6 |
7 | public enum AppDomain {
8 |
9 | DE("de", 17, new Locale("de")),
10 | UK("uk", 43, new Locale("en")),
11 | FR("fr", 18, new Locale("fr")),
12 | NL("nl", 35, new Locale("nl")),
13 | BE("be", 36, new Locale("nl", "BE")),
14 | BEFR("befr", 37, new Locale("fr", "BE")),
15 | COM("com", 38, new Locale("en")),
16 | AT("at", 39, new Locale("de", "AT")),
17 | CH("ch", 40, new Locale("de", "CH")),
18 | CHFR("chfr", 41, new Locale("fr", "CH")),
19 | IT("it", 44, new Locale("it")),
20 | PL("pl", 45, new Locale("pl")),
21 | DEV("dev", 17, new Locale("dev"));
22 |
23 |
24 | private final String countryCode;
25 | private final Locale locale;
26 | private final int appDomainId;
27 |
28 |
29 | AppDomain(String countyCode, int appDomainId, Locale locale) {
30 |
31 | this.appDomainId = appDomainId;
32 | this.countryCode = countyCode;
33 | this.locale = locale;
34 | }
35 |
36 | public String getCountryCode() {
37 | return countryCode;
38 | }
39 |
40 | public Locale getLocale() {
41 | return locale;
42 | }
43 |
44 | public static AppDomain fromCountryCode(final String countryCode) {
45 | for (final AppDomain tld : AppDomain.values()) {
46 | if (tld.getCountryCode().equalsIgnoreCase(countryCode)) {
47 | return tld;
48 | }
49 | }
50 |
51 | switch (countryCode) {
52 |
53 | case "co.uk":
54 | case "gb":
55 | return UK;
56 |
57 | default:
58 | throw new IllegalArgumentException("No constant with countryCode" + countryCode + "found");
59 | }
60 | }
61 |
62 | @Override
63 | public String toString() {
64 | return new ToStringBuilder(this)
65 | .append("countryCode", countryCode)
66 | .append("locale", locale)
67 | .append("appDomainID", appDomainId)
68 | .toString();
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/selenium/config/DomainConfiguration.java:
--------------------------------------------------------------------------------
1 | package selenium.config;
2 |
3 | import selenium.appDomain.AppDomain;
4 | import com.google.common.base.Preconditions;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 | import org.springframework.core.env.Environment;
9 |
10 | @Configuration
11 | public class DomainConfiguration {
12 |
13 | public static final AppDomain APP_DOMAIN = getAppDomain();
14 |
15 | @Autowired
16 | private Environment env;
17 |
18 | private static AppDomain getAppDomain() {
19 | final String countryCode = System.getProperty("country");
20 | Preconditions.checkNotNull(countryCode, "\"country\" system property missing");
21 | return AppDomain.fromCountryCode(countryCode);
22 | }
23 |
24 | @Bean(name = "appUrl")
25 | public String appUrl() {
26 | return env.getProperty("appUrl." + APP_DOMAIN.getCountryCode());
27 | }
28 |
29 | @Bean(name = "browser")
30 | public String browser() {
31 | return env.getProperty("browser");
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/selenium/driver/Driver.java:
--------------------------------------------------------------------------------
1 | package selenium.driver;
2 |
3 | import org.openqa.selenium.WebDriver;
4 | import org.openqa.selenium.WebElement;
5 | import org.openqa.selenium.support.PageFactory;
6 | import org.openqa.selenium.support.ui.ExpectedConditions;
7 | import org.openqa.selenium.support.ui.WebDriverWait;
8 |
9 | public class Driver {
10 |
11 | WebDriver driver;
12 |
13 | public Driver(WebDriver driver) {
14 |
15 | PageFactory.initElements(driver, this);
16 | this.driver = driver;
17 | }
18 |
19 | private static ThreadLocal webDriver = new ThreadLocal<>();
20 |
21 | public static WebDriver getDriver() {
22 |
23 | return webDriver.get();
24 | }
25 |
26 | public static void setWebDriver(WebDriver driver) {
27 |
28 | webDriver.set(driver);
29 | }
30 |
31 | protected void waitForElement(WebElement element) {
32 |
33 | WebDriverWait wait = new WebDriverWait(driver, 15);
34 | WebElement target = wait.until(ExpectedConditions.visibilityOf(element));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/selenium/driver/DriverManager.java:
--------------------------------------------------------------------------------
1 | package selenium.driver;
2 |
3 | import org.openqa.selenium.WebDriver;
4 | import org.openqa.selenium.chrome.ChromeDriver;
5 | import org.openqa.selenium.chrome.ChromeOptions;
6 | import org.openqa.selenium.firefox.FirefoxDriver;
7 | import org.openqa.selenium.firefox.FirefoxOptions;
8 | import org.openqa.selenium.remote.DesiredCapabilities;
9 | import org.openqa.selenium.remote.RemoteWebDriver;
10 |
11 | import java.net.MalformedURLException;
12 | import java.net.URL;
13 |
14 | public class DriverManager {
15 |
16 | private static final String HEADLESS = "headless";
17 | public static WebDriver createInstance(String browserName, String appUrl, String methodName) throws MalformedURLException {
18 | final String browserMode = System.getProperty("mode");
19 | WebDriver driver = null;
20 | if(browserName.toLowerCase().contains("firefox")) {
21 | System.setProperty("webdriver.gecko.driver", "driver/osx/geckodriver");
22 | if(browserMode !=null && browserMode.equals(HEADLESS)){
23 | FirefoxOptions firefoxOptions = new FirefoxOptions();
24 | firefoxOptions.addArguments("--headless");
25 | driver = new FirefoxDriver(firefoxOptions);
26 | }else {
27 | driver = new FirefoxDriver();
28 | }
29 |
30 | }
31 | if(browserName.toLowerCase().contains("chrome")) {
32 | System.setProperty("webdriver.chrome.driver", "driver/osx/chromedriver");
33 | if(browserMode !=null && browserMode.equals(HEADLESS)){
34 | ChromeOptions chromeOptions = new ChromeOptions();
35 | chromeOptions.addArguments("--headless");
36 | driver = new ChromeDriver(chromeOptions);
37 | }else {
38 | driver = new ChromeDriver();
39 | }
40 |
41 | }
42 | if(browserName.toLowerCase().contains("zalenium")) {
43 | DesiredCapabilities cap = DesiredCapabilities.chrome();
44 | cap.setCapability("name", methodName);
45 | driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), cap);
46 | }
47 | driver.navigate().to(appUrl);
48 | return driver;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/selenium/localization/LocaleText.java:
--------------------------------------------------------------------------------
1 | package selenium.localization;
2 |
3 | import selenium.config.DomainConfiguration;
4 | import org.springframework.stereotype.Component;
5 |
6 | import java.nio.charset.Charset;
7 | import java.util.Locale;
8 | import java.util.ResourceBundle;
9 |
10 | @Component
11 | public class LocaleText {
12 |
13 | private static final Locale LOCALE = DomainConfiguration.APP_DOMAIN.getLocale();
14 |
15 |
16 | public static String get(final String key) {
17 |
18 | /*************************************************************************
19 | ** The resource bundle by default uses the ISO 8859-1 character encoding
20 | ** Making it compatible with the commonly used UTF-8 format
21 | *************************************************************************/
22 |
23 | final String value = ResourceBundle.getBundle("locale", LOCALE).getString(key);
24 | final byte[] utf8Bytes = value.getBytes(Charset.forName("ISO-8859-1"));
25 | return new String(utf8Bytes, Charset.forName("UTF-8"));
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/selenium/pageobject/HomePage.java:
--------------------------------------------------------------------------------
1 | package selenium.pageobject;
2 |
3 | import org.openqa.selenium.WebElement;
4 | import org.openqa.selenium.support.FindBy;
5 | import selenium.driver.Driver;
6 | import org.openqa.selenium.WebDriver;
7 |
8 | public class HomePage extends Driver {
9 |
10 | public HomePage(WebDriver driver) {
11 |
12 | super(driver);
13 | }
14 |
15 | @FindBy(css = "a[href='/login']")
16 | private WebElement loginPageLink;
17 |
18 | public String getPageTitle() {
19 | return getDriver().getTitle();
20 | }
21 |
22 | public void goToLoginPage() {
23 |
24 | waitForElement(loginPageLink);
25 | loginPageLink.click();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/selenium/pageobject/LoginPage.java:
--------------------------------------------------------------------------------
1 | package selenium.pageobject;
2 |
3 | import org.openqa.selenium.WebDriver;
4 | import org.openqa.selenium.WebElement;
5 | import org.openqa.selenium.support.FindBy;
6 | import selenium.driver.Driver;
7 |
8 | public class LoginPage extends Driver {
9 |
10 | public LoginPage(WebDriver driver) {
11 | super(driver);
12 | }
13 |
14 | @FindBy(id = "username")
15 | private WebElement usernameField;
16 |
17 | @FindBy(id = "password")
18 | private WebElement passwordField;
19 |
20 | @FindBy(css = "button[type='submit']")
21 | private WebElement submitButton;
22 |
23 | public void login(String username, String password) {
24 | usernameField.sendKeys(username);
25 | passwordField.sendKeys(password);
26 | submitButton.click();
27 | }
28 |
29 | public String getCurrentUrl() {
30 | return getDriver().getCurrentUrl();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/resources/locale_en.properties:
--------------------------------------------------------------------------------
1 | homePage.title=The Internet
--------------------------------------------------------------------------------
/src/test/java/selenium/Application.java:
--------------------------------------------------------------------------------
1 | package selenium;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class Application {
8 |
9 | public static void main(final String[] args) throws Exception {
10 | SpringApplication.run(Application.class, args);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/test/java/selenium/context/Base.java:
--------------------------------------------------------------------------------
1 | package selenium.context;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.beans.factory.annotation.Qualifier;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.boot.test.SpringApplicationConfiguration;
7 | import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
8 | import org.testng.annotations.Listeners;
9 | import selenium.Application;
10 | import selenium.listeners.WebDriverListener;
11 | import selenium.testdata.file.FileLoaderService;
12 |
13 | @Listeners(WebDriverListener.class)
14 | @SpringApplicationConfiguration(Application.class)
15 | public abstract class Base extends AbstractTestNGSpringContextTests {
16 |
17 | @Autowired
18 | @Qualifier("appUrl")
19 | protected String appUrl;
20 |
21 | @Autowired
22 | @Qualifier("browser")
23 | protected String browser;
24 |
25 | @Autowired
26 | protected FileLoaderService fileLoaderService;
27 |
28 | @Value("${spring.profiles.active}")
29 | String profile;
30 |
31 | public String getProfile() {
32 |
33 | return profile;
34 | }
35 |
36 | public String getAppUrl() {
37 | return appUrl;
38 | }
39 |
40 | public String getBrowser() {
41 | return browser;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/test/java/selenium/listeners/WebDriverListener.java:
--------------------------------------------------------------------------------
1 | package selenium.listeners;
2 |
3 | import selenium.driver.Driver;
4 | import selenium.driver.DriverManager;
5 | import io.qameta.allure.Attachment;
6 | import org.apache.commons.io.FileUtils;
7 | import org.apache.commons.io.IOUtils;
8 | import org.openqa.selenium.OutputType;
9 | import org.openqa.selenium.TakesScreenshot;
10 | import org.openqa.selenium.WebDriver;
11 | import org.testng.IInvokedMethod;
12 | import org.testng.IInvokedMethodListener;
13 | import org.testng.ITestResult;
14 | import selenium.context.Base;
15 |
16 | import java.io.File;
17 | import java.io.FileInputStream;
18 | import java.io.IOException;
19 | import java.io.InputStream;
20 | import java.net.MalformedURLException;
21 | import java.text.SimpleDateFormat;
22 | import java.util.Date;
23 |
24 | public class WebDriverListener implements IInvokedMethodListener {
25 |
26 | @Override
27 | public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
28 |
29 | if(method.isTestMethod()) {
30 |
31 | String browserName = ((Base)method.getTestMethod().getInstance()).getBrowser();
32 | try {
33 | WebDriver driver = DriverManager.createInstance(browserName, ((Base)method.getTestMethod().getInstance()).getAppUrl(), method.getTestMethod().getMethodName());
34 | System.out.println("Initializing webdriver session --> Thread ID: " + Thread.currentThread().getId());
35 | System.out.println("Running test --> " + method.getTestMethod().getMethodName());
36 | Driver.setWebDriver(driver);
37 | } catch (MalformedURLException e) {
38 | e.printStackTrace();
39 | }
40 | }
41 | }
42 |
43 | @Override
44 | public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
45 |
46 | if(method.isTestMethod()) {
47 |
48 | WebDriver driver = Driver.getDriver();
49 | if(driver != null) {
50 |
51 | try {
52 | takeScreenshotOnFailure(testResult);
53 | } catch (IOException e) {
54 | e.printStackTrace();
55 | }
56 | System.out.println("Closing webdriver session: " + Thread.currentThread().getId());
57 | driver.quit();
58 | }
59 | }
60 | }
61 |
62 | public void takeScreenshotOnFailure(ITestResult testResult) throws IOException {
63 |
64 | if(testResult.getStatus() == ITestResult.FAILURE) {
65 |
66 | File screenShot = ((TakesScreenshot) Driver.getDriver()).getScreenshotAs(OutputType.FILE);
67 | File destination = new File("target/failure-screenshots/" + testResult.getName() + "-"
68 | + new SimpleDateFormat("dd-MM-yyyy HH-mm-ss").format(new Date()) + ".png");
69 | FileUtils.copyFile(screenShot, destination);
70 |
71 | InputStream screenShotStream = new FileInputStream(destination);
72 | byte[] screen = IOUtils.toByteArray(screenShotStream);
73 |
74 | saveScreenshot(screen);
75 | }
76 | }
77 |
78 | @Attachment(value = "Screenshot of the failure", type = "image/png")
79 | public byte[] saveScreenshot(byte[] screenShot) {
80 |
81 | return screenShot;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/test/java/selenium/testdata/file/FileLoaderService.java:
--------------------------------------------------------------------------------
1 | package selenium.testdata.file;
2 |
3 |
4 |
5 | import com.fasterxml.jackson.databind.ObjectMapper;
6 | import selenium.config.DomainConfiguration;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.core.io.Resource;
9 | import org.springframework.core.io.ResourceLoader;
10 | import org.springframework.stereotype.Service;
11 | import selenium.testdata.properties.User;
12 |
13 | import java.io.IOException;
14 |
15 | @Service
16 | public class FileLoaderService {
17 |
18 | private static final String TEST_DATA_FOLDER = "testdata";
19 | private static final String USER_FOLDER = "user";
20 |
21 | private final ObjectMapper objectMapper;
22 | private final ResourceLoader resourceLoader;
23 |
24 | @Autowired
25 | public FileLoaderService(ObjectMapper objectMapper, ResourceLoader resourceLoader) {
26 | this.objectMapper = objectMapper;
27 | this.resourceLoader = resourceLoader;
28 | }
29 |
30 | public User getUser(final String fileNameWithoutCountryCodeAndExtention) {
31 | return load(USER_FOLDER + "/" + fileNameWithoutCountryCodeAndExtention + "_"
32 | + DomainConfiguration.APP_DOMAIN.getCountryCode() + ".json", User.class);
33 | }
34 |
35 | private T load(final String filename, final Class type) {
36 | try{
37 | final Resource resource = resourceLoader.getResource(getFullPath(filename));
38 | return objectMapper.readValue(resource.getInputStream(), type);
39 | }catch (final IOException e) {
40 | throw new RuntimeException("Failed to load test data", e);
41 | }
42 | }
43 |
44 | private String getFullPath(final String filename) {
45 | return TEST_DATA_FOLDER + "/" + filename;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/test/java/selenium/testdata/properties/User.java:
--------------------------------------------------------------------------------
1 | package selenium.testdata.properties;
2 |
3 | import org.apache.commons.lang3.builder.ToStringBuilder;
4 |
5 | public class User {
6 | private String email;
7 | private String username;
8 | private String password;
9 | private String gender;
10 | private String firstname;
11 | private String lastname;
12 | private String address;
13 | private String zip;
14 | private String city;
15 | private String cardtype;
16 | private String cardnumber;
17 | private String expiremonth;
18 | private String expireyear;
19 | private String ccvnumber;
20 | private String country;
21 | private String telephone;
22 |
23 | public String getPassword() {
24 | return password;
25 | }
26 |
27 | public void setPassword(final String password) {
28 | this.password = password;
29 | }
30 |
31 | public String getEmail() {
32 | return email;
33 | }
34 |
35 | public void setEmail(final String email) {
36 | this.email = email;
37 | }
38 |
39 | public String getUsername() {return username; }
40 |
41 | public void setUsername(final String username) { this.username = username; }
42 |
43 | public String getGender() {
44 | return gender;
45 | }
46 |
47 | public void setGender(final String gender) {
48 | this.gender = gender;
49 | }
50 |
51 | public String getFirstname() {
52 | return firstname;
53 | }
54 |
55 | public void setFirstname(final String firstname) {
56 | this.firstname = firstname;
57 | }
58 |
59 | public String getLastname() {
60 | return lastname;
61 | }
62 |
63 | public void setLastname(final String lastname) {
64 | this.lastname = lastname;
65 | }
66 |
67 | public String getAddress() {
68 | return address;
69 | }
70 |
71 | public void setAddress(String address) {
72 | this.address = address;
73 | }
74 |
75 | public String getZip() {
76 | return zip;
77 | }
78 |
79 | public void setZip(String zip) {
80 | this.zip = zip;
81 | }
82 |
83 | public String getCity() {
84 | return city;
85 | }
86 |
87 | public void setCity(String city) {
88 | this.city = city;
89 | }
90 |
91 | public String getCardtype() {
92 | return cardtype;
93 | }
94 |
95 | public void setCardtype(String cardtype) {
96 | this.cardtype = cardtype;
97 | }
98 |
99 | public String getCardnumber() {
100 | return cardnumber;
101 | }
102 |
103 | public void setCardnumber(String cardnumber) {
104 | this.cardnumber = cardnumber;
105 | }
106 |
107 | public String getExpiremonth() {
108 | return expiremonth;
109 | }
110 |
111 | public void setExpiremonth(String expiremonth) {
112 | this.expiremonth = expiremonth;
113 | }
114 |
115 | public String getExpireyear() {
116 | return expireyear;
117 | }
118 |
119 | public void setExpireyear(String expireyear) {
120 | this.expireyear = expireyear;
121 | }
122 |
123 | public String getCcvnumber() {
124 | return ccvnumber;
125 | }
126 |
127 | public void setCcvnumber(String ccvnumber) {
128 | this.ccvnumber = ccvnumber;
129 | }
130 |
131 | public String getCountry() {
132 | return country;
133 | }
134 |
135 | public void setCountry(String country) {
136 | this.country = country;
137 | }
138 |
139 | public String getTelephone() {
140 | return telephone;
141 | }
142 |
143 | public void setTelephone(String telephone) {
144 | this.telephone = telephone;
145 | }
146 |
147 | @Override
148 | public String toString() {
149 | return new ToStringBuilder(this)
150 | .append("email", email)
151 | .append("password", password)
152 | .build();
153 | }
154 | }
155 |
156 |
--------------------------------------------------------------------------------
/src/test/java/selenium/tests/SimpleTestExamples.java:
--------------------------------------------------------------------------------
1 | package selenium.tests;
2 |
3 | import selenium.driver.Driver;
4 | import io.qameta.allure.Description;
5 | import selenium.localization.LocaleText;
6 | import org.testng.annotations.Test;
7 | import selenium.pageobject.HomePage;
8 | import selenium.context.Base;
9 | import selenium.pageobject.LoginPage;
10 | import selenium.testdata.properties.User;
11 |
12 | import static org.hamcrest.MatcherAssert.assertThat;
13 | import static org.hamcrest.Matchers.equalTo;
14 |
15 | public class SimpleTestExamples extends Base {
16 |
17 | @Test(description = "Page title test")
18 | @Description("Checks if the page title is correct")
19 | public void pageTitleTest() {
20 |
21 | HomePage homePage = new HomePage(Driver.getDriver());
22 | assertThat(homePage.getPageTitle(), equalTo(LocaleText.get("homePage.title")));
23 | }
24 |
25 | @Test(description = "Authentication test")
26 | @Description("Checks if user is able to log in")
27 | public void loginTest() {
28 |
29 | User user = fileLoaderService.getUser("user");
30 |
31 | HomePage homePage = new HomePage(Driver.getDriver());
32 | homePage.goToLoginPage();
33 |
34 | LoginPage loginPage = new LoginPage(Driver.getDriver());
35 | loginPage.login(user.getUsername(), user.getPassword());
36 |
37 | assertThat(loginPage.getCurrentUrl(), equalTo(appUrl + "secure"));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/test/resources/application-release.properties:
--------------------------------------------------------------------------------
1 | appUrl.com=http://the-internet.herokuapp.com/
--------------------------------------------------------------------------------
/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 | appUrl.com=http://the-internet.herokuapp.com/
--------------------------------------------------------------------------------
/src/test/resources/testdata/user/user_com.json:
--------------------------------------------------------------------------------
1 | {
2 | "gender": "MALE",
3 | "username": "tomsmith",
4 | "firstname": "Selenium",
5 | "lastname": "TestUser",
6 | "telephone": "0123456789",
7 | "email": "some@email.com",
8 | "password": "SuperSecretPassword!",
9 | "address": "Am Treptower Park 28",
10 | "zip": "12435",
11 | "city": "Berlin",
12 | "cardtype": "VISA",
13 | "cardnumber": "4111 1111 1111 1111",
14 | "expiremonth": "08",
15 | "expireyear": "2018",
16 | "ccvnumber": "737"
17 | }
--------------------------------------------------------------------------------
/testng.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------