diff --git a/.github/ISSUE_TEMPLATE/need-help-with-ui-automation-bootstrap.md b/.github/ISSUE_TEMPLATE/need-help-with-test-automation-bootstrap.md
similarity index 71%
rename from .github/ISSUE_TEMPLATE/need-help-with-ui-automation-bootstrap.md
rename to .github/ISSUE_TEMPLATE/need-help-with-test-automation-bootstrap.md
index c14a056..9c9d061 100644
--- a/.github/ISSUE_TEMPLATE/need-help-with-ui-automation-bootstrap.md
+++ b/.github/ISSUE_TEMPLATE/need-help-with-test-automation-bootstrap.md
@@ -1,5 +1,5 @@
---
-name: Need help with ui-automation-bootstrap
+name: Need help with test-automation-bootstrap
about: Ask a general how-to question.
title: ''
labels: 'type: triage/discussion'
diff --git a/.gitignore b/.gitignore
index 402eca6..aafa4e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ target/
*.iml
/reports/ExtentReport.html
/.vscode
+secrets/
diff --git a/README.md b/README.md
index ea16d19..0da1c65 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-
UI Automation Bootstrap
+Test Automation Bootstrap
@@ -38,18 +38,16 @@
* [Changelog](#changelog)
* [Contributing](#contributing)
-## What does a _ui-automation-bootstrap_ test look like?
+## What does a _test-automation-bootstrap_ test look like?
```java
@Test
@Mock(clazz = MockExampleModel.class)
public void shouldPerformSearchSuccessfully() {
- open("http://google.com");
+ open("https://google.com");
googleSearchPage
.searchComponent()
- .searchFor("mock");
-
- googleResultsPage
+ .searchFor("mock")
.searchComponent()
.self()
.shouldHave(value("mock"));
@@ -57,7 +55,7 @@ public void shouldPerformSearchSuccessfully() {
```
## About
-A simple and effective template to quickstart any ui test automation framework in no time!
+A simple and effective template to quickstart any test automation framework in no time.
##### Using the goods of
* _[Selenide](https://github.com/selenide/selenide)_ - A selenium wrapper for concise UI tests
@@ -65,6 +63,7 @@ A simple and effective template to quickstart any ui test automation framework i
* _[SonarQube](https://www.sonarqube.org/)_ 🐳 - A static analysis tool
* _[SeleniumGrid](https://github.com/SeleniumHQ/docker-selenium)_ 🐳 - Allows to scale the test execution as well as providing the required browser types
* _[Checkstyle](https://maven.apache.org/plugins/maven-checkstyle-plugin/)_ - Code linter
+* _[ELK Stack](https://www.elastic.co/blog/elastic-stack-7-10-1-released)_ 🐳 - Enables distributed log aggregation and visualization
> _🐳 stands for dockerized_
@@ -85,4 +84,4 @@ Available [here](/docs/CHANGELOG.md).
## Contributing
Open source from the first commit ✨
-Dive into ui-automation-bootstrap's [contribution guide](docs/CONTRIBUTING.md).
+Dive into test-automation-bootstrap's [contribution guide](docs/CONTRIBUTING.md).
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 750d824..86eb974 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -1,33 +1,33 @@
## Change Log
### v1.6.1 (2020/07/02 08:53 +00:00)
-- [#29](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/29) 🐛 Fix logback configuration to default package (#29) (@sergiomartins8)
+- [#29](https://github.com/sergiomartins8/test-automation-bootstrap/pull/29) 🐛 Fix logback configuration to default package (#29) (@sergiomartins8)
### v1.6.0 (2020/06/22 18:02 +00:00)
-- [#27](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/27) ⬆️ Upgrade to selenide:5.12.2 (#27) (@sergiomartins8)
+- [#27](https://github.com/sergiomartins8/test-automation-bootstrap/pull/27) ⬆️ Upgrade to selenide:5.12.2 (#27) (@sergiomartins8)
### v1.5.0 (2020/05/26 10:16 +00:00)
-- [#26](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/26) ⬆️ Upgrade to selenide:5.12.1 (#26) (@sergiomartins8)
-- [#25](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/25) 🔥 Revamp structure (#25) (@sergiomartins8)
+- [#26](https://github.com/sergiomartins8/test-automation-bootstrap/pull/26) ⬆️ Upgrade to selenide:5.12.1 (#26) (@sergiomartins8)
+- [#25](https://github.com/sergiomartins8/test-automation-bootstrap/pull/25) 🔥 Revamp structure (#25) (@sergiomartins8)
### v1.4.0 (2020/05/24 14:38 +00:00)
-- [#24](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/24) ☀️ Travis Integration (#24) (@sergiomartins8)
+- [#24](https://github.com/sergiomartins8/test-automation-bootstrap/pull/24) ☀️ Travis Integration (#24) (@sergiomartins8)
### v1.3.0 (2020/05/21 08:32 +00:00)
-- [#23](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/23) ☀️ Jenkins Integration (#23) (@sergiomartins8)
-- [#22](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/22) 🤖 Revamp CI/CD pipelines (#22) (@sergiomartins8)
+- [#23](https://github.com/sergiomartins8/test-automation-bootstrap/pull/23) ☀️ Jenkins Integration (#23) (@sergiomartins8)
+- [#22](https://github.com/sergiomartins8/test-automation-bootstrap/pull/22) 🤖 Revamp CI/CD pipelines (#22) (@sergiomartins8)
### v1.2.0 (2020/05/11 15:28 +00:00)
-- [#21](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/21) ✅ Refactor test examples (#21) (@sergiomartins8)
+- [#21](https://github.com/sergiomartins8/test-automation-bootstrap/pull/21) ✅ Refactor test examples (#21) (@sergiomartins8)
### v1.1.0 (2020/05/09 17:49 +00:00)
-- [#20](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/20) 🐛 Fix firefox integration tests (#20) (@sergiomartins8)
+- [#20](https://github.com/sergiomartins8/test-automation-bootstrap/pull/20) 🐛 Fix firefox integration tests (#20) (@sergiomartins8)
### v1.0.0 (2020/05/06 06:59 +00:00)
-- [#18](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/18) ☀️ Moving to archetype (#18) (@sergiomartins8)
-- [#16](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/16) 🤖 Github actions CI (#16) (Sérgio Martins)
-- [#15](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/15) CI/CD - github actions (#15) (Sérgio Martins)
-- [#13](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/13) revamp current system properties management (#13) (Sérgio Martins)
-- [#10](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/10) revamp mock listener and mock model (#10) (Sérgio Martins)
-- [#8](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/8) Upgrade Extent Reports to version 4 (#8) (Sérgio Martins)
-- [#7](https://github.com/sergiomartins8/ui-automation-bootstrap/pull/7) add browser to system properties (#7) (Sérgio Martins)
\ No newline at end of file
+- [#18](https://github.com/sergiomartins8/test-automation-bootstrap/pull/18) ☀️ Moving to archetype (#18) (@sergiomartins8)
+- [#16](https://github.com/sergiomartins8/test-automation-bootstrap/pull/16) 🤖 Github actions CI (#16) (Sérgio Martins)
+- [#15](https://github.com/sergiomartins8/test-automation-bootstrap/pull/15) CI/CD - github actions (#15) (Sérgio Martins)
+- [#13](https://github.com/sergiomartins8/test-automation-bootstrap/pull/13) revamp current system properties management (#13) (Sérgio Martins)
+- [#10](https://github.com/sergiomartins8/test-automation-bootstrap/pull/10) revamp mock listener and mock model (#10) (Sérgio Martins)
+- [#8](https://github.com/sergiomartins8/test-automation-bootstrap/pull/8) Upgrade Extent Reports to version 4 (#8) (Sérgio Martins)
+- [#7](https://github.com/sergiomartins8/test-automation-bootstrap/pull/7) add browser to system properties (#7) (Sérgio Martins)
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index 68ca66c..9c317a5 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -1,6 +1,6 @@
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
-The following is a set of guidelines for contributing to ui-automation-bootstrap.
+The following is a set of guidelines for contributing to test-automation-bootstrap.
These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
#### Table of contents
@@ -18,21 +18,21 @@ These are mostly guidelines, not rules. Use your best judgment, and feel free to
## I just have a question!
-Questions and/or discussions are tracked as [issues](https://github.com/sergiomartins8/ui-automation-bootstrap/issues).
-Fill in [the template](../.github/ISSUE_TEMPLATE/need-help-with-ui-automation-bootstrap.md).
+Questions and/or discussions are tracked as [issues](https://github.com/sergiomartins8/test-automation-bootstrap/issues).
+Fill in [the template](../.github/ISSUE_TEMPLATE/need-help-with-test-automation-bootstrap.md).
## How can I contribute?
### Reporting bugs
-Bug reports are tracked as [issues](https://github.com/sergiomartins8/ui-automation-bootstrap/issues).
+Bug reports are tracked as [issues](https://github.com/sergiomartins8/test-automation-bootstrap/issues).
Fill in [the template](../.github/ISSUE_TEMPLATE/bug_report.md), the information it asks for helps to resolve issues faster.
> **Note:** If you find a **closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.
### Suggesting Enhancements
-Enhancement suggestions are tracked as [issues](https://github.com/sergiomartins8/ui-automation-bootstrap/issues).
+Enhancement suggestions are tracked as [issues](https://github.com/sergiomartins8/test-automation-bootstrap/issues).
Fill in [the template](../.github/ISSUE_TEMPLATE/enhancement.md), including the steps that you imagine you would take if the feature you're requesting existed.
### Your first code contribution
@@ -46,9 +46,9 @@ Unsure where to begin contributing? You can start by looking for **utils** metho
The process described here has several goals:
-- Maintain ui-automation-bootstrap's quality
+- Maintain test-automation-bootstrap's quality
- Fix problems that are important to users
-- Engage the community in working toward the best possible ui automation template ✨
+- Engage the community in working toward the best possible test automation template ✨
- Enable a sustainable system for maintaining and review contributions
Please follow these steps to have your contribution considered:
diff --git a/docs/documentation.md b/docs/documentation.md
index 47495a2..1d860a8 100644
--- a/docs/documentation.md
+++ b/docs/documentation.md
@@ -1,4 +1,4 @@
-The following is a set of guidelines and documentation to better experience the ui-automation-bootstrap's features.
+The following is a set of guidelines and documentation to better experience the test-automation-bootstrap's features.
These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
#### Table of contents
@@ -18,8 +18,10 @@ These are mostly guidelines, not rules. Use your best judgment, and feel free to
[Jenkins](#jenkins-)
+[ELK Stack](#elk-stack)
+
## POM - the Page Object Model
-The *ui-automation-bootstrap* uses the Page Object Model (**POM**) (https://martinfowler.com/bliki/PageObject.html) to structure code.
+The *test-automation-bootstrap* uses the Page Object Model (**POM**) (https://martinfowler.com/bliki/PageObject.html) to structure code.
![](img/structure.gif)
@@ -45,7 +47,7 @@ You can run tests in parallel, configuring your suite file or with system proper
##### Example
```shell script
-$ mvn clean test -Dparallel= -DthreadCount=
+$ mvn clean test -Dparallel= -Dthread.count=
```
## Extent Reports
@@ -125,7 +127,7 @@ $ mvn -B clean verify sonar:sonar \
```
## Jenkins 🤖
-There is a [jenkinsfile](../Jenkinsfile) example available. Use it to get started. However, it might need some tailoring.
+There is a [Jenkinsfile](../Jenkinsfile) example available. Use it to get started. However, it might need some tailoring.
##### Snippet
```groovy
@@ -155,3 +157,69 @@ podTemplate(label: "jenkins-slave-base-pod", serviceAccount: "jenkins", containe
```
> The example above uses Jenkins on Kubernetes. Follow this [article](https://medium.com/@sergiomartins8/highly-scalable-jenkins-on-minikube-8cc289a31850) to have a similar environment in no time!
+>
+> Furthermore, the source code for the base image is open source and available [here](https://github.com/sergiomartins8/jenkins-slave-base).
+
+## ELK Stack
+
+> Check out the related distributed test reporting article on [medium](https://medium.com/@sergiomartins8/distributed-test-reporting-using-elk-stack-97dd699d6bb4).
+
+Elastic Stack (**ELK**) Docker Composition, preconfigured with **Security**, **Monitoring**, and **Tools**; Up with a Single Command.
+Based on [Official Elastic Docker Images](https://www.docker.elastic.co/)
+
+Stack Version: [7.10.1](https://www.elastic.co/blog/elastic-stack-7-10-1-released)
+> You can change Elastic Stack version by setting `ELK_VERSION` in `.env` file and rebuild your images. Any version >= 7.0.0 is compatible with this template.
+
+This allows you to build your own distributed test reporting dashboards using pie charts, timeline analysis, and all other kinds of desired visualizations.
+The options are endless.
+
+##### Example 1
+![](img/elk_1.png)
+
+##### Example 2
+![](img/elk_2.png)
+
+#### Requirements
+- [Docker 17.05 or higher](https://docs.docker.com/install/)
+- [Docker-Compose 3 or higher](https://docs.docker.com/compose/install/)
+- 4GB RAM (For Windows and MacOS make sure Docker's VM has more than 4GB+ memory.)
+
+#### Setup
+1. Initialize Elasticsearch Keystore and TLS Self-Signed Certificates
+```shell script
+$ make setup
+```
+> **For Linux's docker hosts only**. By default virtual memory [is not enough](https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html) so run the next command as root `sysctl -w vm.max_map_count=262144`
+1. Start Elastic Stack
+```shell script
+$ make elk $ docker-compose up -d
+```
+1. Visit Kibana at [https://localhost:5601](https://localhost:5601) or `https://:5601`
+
+Default Username: `elastic`, Password: `kibana`
+
+> - Notice that Kibana is configured to use HTTPS, so you'll need to write `https://` before `localhost:5601` in the browser.
+> - Modify `.env` file for your needs, most importantly `ELASTIC_PASSWORD` that setup your superuser `elastic`'s password, `ELASTICSEARCH_HEAP` & `LOGSTASH_HEAP` for Elasticsearch & Logstash Heap Size.
+
+Whatever your host (e.g AWS EC2, Azure, DigitalOcean, or on-premise server), once you expose your host to the network, ELK component will be accessible on their respective ports.
+
+#### Setting Up Keystore
+You can extend the Keystore generation script by adding keys to `./setup/keystore.sh` script. (e.g Add S3 Snapshot Repository Credentials)
+
+To Re-generate Keystore:
+```shell script
+$ make keystore
+```
+
+#### Enable SSL on HTTP
+By default, Transport Layer has SSL enabled as well as SSL on HTTP layer.
+
+> ⚠️ Thus, as SSL on HTTP layer is enabled, it will require that all clients that connect to Elasticsearch have to configure SSL connection for HTTP, this includes all the current configured parts of the stack (e.g Logstash, Kibana, Curator, etc) plus any library/binding that connects to Elasticsearch from your application code.
+
+In order to send out your logs to logstash use the [DistributedReportListener](../src/test/java/io/company/utils/listeners/DistributedReportListener.java) class.
+It has a base implementation, but tailored it accordingly.
+
+##### Example
+```shell script
+$ mvn clean test -Dlistener=${package}/utils/listeners/DistributedReportListener.java
+```
diff --git a/docs/img/elk_1.png b/docs/img/elk_1.png
new file mode 100644
index 0000000..c913849
Binary files /dev/null and b/docs/img/elk_1.png differ
diff --git a/docs/img/elk_2.png b/docs/img/elk_2.png
new file mode 100644
index 0000000..d0e02a2
Binary files /dev/null and b/docs/img/elk_2.png differ
diff --git a/elk-stack/.env b/elk-stack/.env
new file mode 100644
index 0000000..2240242
--- /dev/null
+++ b/elk-stack/.env
@@ -0,0 +1,31 @@
+COMPOSE_PROJECT_NAME=elastic
+ELK_VERSION=7.10.1
+
+#----------- Resources --------------------------#
+ELASTICSEARCH_HEAP=256m
+LOGSTASH_HEAP=256m
+
+#----------- Hosts and Ports --------------------#
+# To be able to further "de-compose" the compose files, get hostnames from environment variables instead.
+
+ELASTICSEARCH_HOST=elasticsearch
+ELASTICSEARCH_PORT=9200
+
+KIBANA_HOST=kibana
+KIBANA_PORT=5601
+
+#----------- Credientals ------------------------#
+# Username & Password for Admin Elasticsearch cluster.
+# This is used to set the password at setup, and used by others to connect to Elasticsearch at runtime.
+ELASTIC_USERNAME=elastic
+ELASTIC_PASSWORD=kibana
+AWS_ACCESS_KEY_ID=nottherealid
+AWS_SECRET_ACCESS_KEY=notherealsecret
+
+#----------- Cluster ----------------------------#
+ELASTIC_CLUSTER_NAME=elastdocker-cluster
+ELASTIC_INIT_MASTER_NODE=elastdocker-node-0
+ELASTIC_NODE_NAME=elastdocker-node-0
+
+# Hostnames of master eligble elasticsearch instances. (matches compose generated host name)
+ELASTIC_DISCOVERY_SEEDS=elasticsearch
diff --git a/elk-stack/Makefile b/elk-stack/Makefile
new file mode 100644
index 0000000..685041c
--- /dev/null
+++ b/elk-stack/Makefile
@@ -0,0 +1,56 @@
+.DEFAULT_GOAL:=help
+
+COMPOSE_ALL_FILES := -f docker-compose.yml
+ELK_SERVICES := elasticsearch logstash kibana
+ELK_MAIN_SERVICES := ${ELK_SERVICES}
+ELK_ALL_SERVICES := ${ELK_MAIN_SERVICES}
+# --------------------------
+
+# load .env so that Docker Swarm Commands has .env values too. (https://github.com/moby/moby/issues/29133)
+include .env
+export
+
+# --------------------------
+.PHONY: setup keystore certs all elk monitoring tools build down stop restart rm logs
+
+keystore: ## Setup Elasticsearch Keystore, by initializing passwords, and add credentials defined in `keystore.sh`.
+ docker-compose -f docker-compose.setup.yml run --rm keystore
+
+certs: ## Generate Elasticsearch SSL Certs.
+ docker-compose -f docker-compose.setup.yml run --rm certs
+
+setup: ## Generate Elasticsearch SSL Certs and Keystore.
+ @make certs
+ @make keystore
+
+elk: ## Start ELK.
+ docker-compose up -d --build
+
+build: ## Build ELK and all its extra components.
+ @docker-compose ${COMPOSE_ALL_FILES} build ${ELK_ALL_SERVICES}
+
+down: ## Down ELK and all its extra components.
+ @docker-compose ${COMPOSE_ALL_FILES} down
+
+stop: ## Stop ELK and all its extra components.
+ @docker-compose ${COMPOSE_ALL_FILES} stop ${ELK_ALL_SERVICES}
+
+restart: ## Restart ELK and all its extra components.
+ @docker-compose ${COMPOSE_ALL_FILES} restart ${ELK_ALL_SERVICES}
+
+rm: ## Remove ELK and all its extra components containers.
+ @docker-compose $(COMPOSE_ALL_FILES) rm -f ${ELK_ALL_SERVICES}
+
+logs: ## Tail all logs with -n 1000.
+ @docker-compose $(COMPOSE_ALL_FILES) logs --follow --tail=1000 ${ELK_ALL_SERVICES}
+
+images: ## Show all Images of ELK and all its extra components.
+ @docker-compose $(COMPOSE_ALL_FILES) images ${ELK_ALL_SERVICES}
+
+prune: ## Remove ELK Containers and Delete Volume Data
+ @make stop && make rm
+ @docker volume prune -f
+
+help: ## Show this help.
+ @echo "Make Application Docker Images and Containers using Docker-Compose files in 'docker' Dir."
+ @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m (default: help)\n\nTargets:\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-12s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
diff --git a/elk-stack/docker-compose.setup.yml b/elk-stack/docker-compose.setup.yml
new file mode 100644
index 0000000..250fe86
--- /dev/null
+++ b/elk-stack/docker-compose.setup.yml
@@ -0,0 +1,29 @@
+version: '3.5'
+
+services:
+ keystore:
+ build:
+ context: elasticsearch/
+ args:
+ ELK_VERSION: ${ELK_VERSION}
+ command: bash /setup/setup-keystore.sh
+ user: "0"
+ volumes:
+ - ./secrets:/secrets
+ - ./setup/:/setup/
+ environment:
+ ELASTIC_PASSWORD: ${ELASTIC_PASSWORD}
+ # Add keystore values used in `keystore.sh` here. (e.g AMAZON S3 Repo Creds)
+ AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
+ AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
+
+ certs:
+ build:
+ context: elasticsearch/
+ args:
+ ELK_VERSION: ${ELK_VERSION}
+ command: bash /setup/setup-certs.sh
+ user: "0"
+ volumes:
+ - ./secrets:/secrets
+ - ./setup/:/setup/
\ No newline at end of file
diff --git a/elk-stack/docker-compose.yml b/elk-stack/docker-compose.yml
new file mode 100644
index 0000000..f520fbf
--- /dev/null
+++ b/elk-stack/docker-compose.yml
@@ -0,0 +1,104 @@
+version: '3.5'
+
+# To Join any other app setup using another network, change name and set external = true
+networks:
+ default:
+ name: elastic
+ external: false
+
+# will contain all elasticsearch data.
+volumes:
+ elasticsearch-data:
+
+secrets:
+ elasticsearch.keystore:
+ file: ./secrets/keystore/elasticsearch.keystore
+ elastic.ca:
+ file: ./secrets/certs/ca/ca.crt
+ elasticsearch.certificate:
+ file: ./secrets/certs/elasticsearch/elasticsearch.crt
+ elasticsearch.key:
+ file: ./secrets/certs/elasticsearch/elasticsearch.key
+ kibana.certificate:
+ file: ./secrets/certs/kibana/kibana.crt
+ kibana.key:
+ file: ./secrets/certs/kibana/kibana.key
+
+services:
+ elasticsearch:
+ image: elasticsearch:elastdocker-${ELK_VERSION}
+ build:
+ context: elasticsearch/
+ args:
+ ELK_VERSION: ${ELK_VERSION}
+ restart: unless-stopped
+ environment:
+ ELASTIC_USERNAME: ${ELASTIC_USERNAME}
+ ELASTIC_PASSWORD: ${ELASTIC_PASSWORD}
+ ELASTIC_CLUSTER_NAME: ${ELASTIC_CLUSTER_NAME}
+ ELASTIC_NODE_NAME: ${ELASTIC_NODE_NAME}
+ ELASTIC_INIT_MASTER_NODE: ${ELASTIC_INIT_MASTER_NODE}
+ ELASTIC_DISCOVERY_SEEDS: ${ELASTIC_DISCOVERY_SEEDS}
+ ES_JAVA_OPTS: -Xmx${ELASTICSEARCH_HEAP} -Xms${ELASTICSEARCH_HEAP} -Des.enforce.bootstrap.checks=true
+ bootstrap.memory_lock: "true"
+ volumes:
+ - elasticsearch-data:/usr/share/elasticsearch/data
+ - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
+ secrets:
+ - source: elasticsearch.keystore
+ target: /usr/share/elasticsearch/config/elasticsearch.keystore
+ - source: elastic.ca
+ target: /usr/share/elasticsearch/config/certs/ca.crt
+ - source: elasticsearch.certificate
+ target: /usr/share/elasticsearch/config/certs/elasticsearch.crt
+ - source: elasticsearch.key
+ target: /usr/share/elasticsearch/config/certs/elasticsearch.key
+ ports:
+ - "9200:9200"
+ - "9300:9300"
+
+ logstash:
+ image: logstash:elastdocker-${ELK_VERSION}
+ build:
+ context: logstash/
+ args:
+ ELK_VERSION: $ELK_VERSION
+ restart: unless-stopped
+ volumes:
+ - ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro
+ - ./logstash/config/pipelines.yml:/usr/share/logstash/config/pipelines.yml:ro
+ - ./logstash/pipeline:/usr/share/logstash/pipeline:ro
+ environment:
+ ELASTIC_USERNAME: ${ELASTIC_USERNAME}
+ ELASTIC_PASSWORD: ${ELASTIC_PASSWORD}
+ ELASTICSEARCH_HOST_PORT: https://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}
+ LS_JAVA_OPTS: "-Xmx${LOGSTASH_HEAP} -Xms${LOGSTASH_HEAP}"
+ secrets:
+ - source: elastic.ca
+ target: /certs/ca.crt
+ ports:
+ - "5000:5000/tcp"
+ - "9600:9600"
+
+ kibana:
+ image: kibana:elastdocker-${ELK_VERSION}
+ build:
+ context: kibana/
+ args:
+ ELK_VERSION: $ELK_VERSION
+ restart: unless-stopped
+ volumes:
+ - ./kibana/config/:/usr/share/kibana/config:ro
+ environment:
+ ELASTIC_USERNAME: ${ELASTIC_USERNAME}
+ ELASTIC_PASSWORD: ${ELASTIC_PASSWORD}
+ ELASTICSEARCH_HOST_PORT: https://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}
+ secrets:
+ - source: elastic.ca
+ target: /certs/ca.crt
+ - source: kibana.certificate
+ target: /certs/kibana.crt
+ - source: kibana.key
+ target: /certs/kibana.key
+ ports:
+ - "5601:5601"
diff --git a/elk-stack/elasticsearch/Dockerfile b/elk-stack/elasticsearch/Dockerfile
new file mode 100644
index 0000000..70e33ff
--- /dev/null
+++ b/elk-stack/elasticsearch/Dockerfile
@@ -0,0 +1,12 @@
+ARG ELK_VERSION
+
+# https://github.com/elastic/elasticsearch-docker
+FROM docker.elastic.co/elasticsearch/elasticsearch:${ELK_VERSION}
+
+# Add healthcheck
+COPY scripts/docker-healthcheck .
+HEALTHCHECK CMD sh ./docker-healthcheck
+
+# Add your elasticsearch plugins setup here
+# Example: RUN elasticsearch-plugin install analysis-icu
+#RUN elasticsearch-plugin install --batch repository-s3
diff --git a/elk-stack/elasticsearch/config/elasticsearch.yml b/elk-stack/elasticsearch/config/elasticsearch.yml
new file mode 100644
index 0000000..14bdf61
--- /dev/null
+++ b/elk-stack/elasticsearch/config/elasticsearch.yml
@@ -0,0 +1,34 @@
+## Default Elasticsearch configuration from Elasticsearch base image.
+## https://github.com/elastic/elasticsearch/blob/master/distribution/docker/src/docker/config/elasticsearch.yml
+#
+cluster.name: ${ELASTIC_CLUSTER_NAME}
+node.name: ${ELASTIC_NODE_NAME}
+network.host: 0.0.0.0
+transport.host: 0.0.0.0
+
+## Cluster Settings
+discovery.seed_hosts: ${ELASTIC_DISCOVERY_SEEDS}
+cluster.initial_master_nodes: ${ELASTIC_INIT_MASTER_NODE}
+
+## License
+xpack.license.self_generated.type: basic
+
+# Security
+xpack.security.enabled: true
+
+## - ssl
+xpack.security.transport.ssl.enabled: true
+xpack.security.transport.ssl.verification_mode: certificate
+xpack.security.transport.ssl.key: certs/elasticsearch.key
+xpack.security.transport.ssl.certificate: certs/elasticsearch.crt
+xpack.security.transport.ssl.certificate_authorities: certs/ca.crt
+
+## - http
+xpack.security.http.ssl.enabled: true
+xpack.security.http.ssl.key: certs/elasticsearch.key
+xpack.security.http.ssl.certificate: certs/elasticsearch.crt
+xpack.security.http.ssl.certificate_authorities: certs/ca.crt
+xpack.security.http.ssl.client_authentication: optional
+
+# Monitoring
+xpack.monitoring.collection.enabled: true
diff --git a/elk-stack/elasticsearch/scripts/docker-healthcheck b/elk-stack/elasticsearch/scripts/docker-healthcheck
new file mode 100644
index 0000000..89f5820
--- /dev/null
+++ b/elk-stack/elasticsearch/scripts/docker-healthcheck
@@ -0,0 +1,14 @@
+#!/bin/bash
+set -eo pipefail
+
+host="$(hostname --ip-address || echo '127.0.0.1')"
+
+if health="$(curl -fsSL "http://$ELASTIC_USERNAME:$ELASTIC_PASSWORD@$host:9200/_cat/health?h=status")"; then
+ health="$(echo "$health" | sed -r 's/^[[:space:]]+|[[:space:]]+$//g')" # trim whitespace (otherwise we'll have "green ")
+ if [ "$health" = 'green' ] || [ "$health" = "yellow" ]; then
+ exit 0
+ fi
+ echo >&2 "unexpected health status: $health"
+fi
+
+exit 1
diff --git a/elk-stack/kibana/Dockerfile b/elk-stack/kibana/Dockerfile
new file mode 100644
index 0000000..9acb332
--- /dev/null
+++ b/elk-stack/kibana/Dockerfile
@@ -0,0 +1,13 @@
+ARG ELK_VERSION
+
+# https://github.com/elastic/kibana-docker
+FROM docker.elastic.co/kibana/kibana:${ELK_VERSION}
+ARG ELK_VERSION
+
+# Add healthcheck
+COPY scripts/docker-healthcheck .
+HEALTHCHECK CMD sh ./docker-healthcheck
+
+# Add your kibana plugins setup here
+# Example: RUN kibana-plugin install
+#RUN kibana-plugin install https://github.com/bitsensor/elastalert-kibana-plugin/releases/download/1.1.0/elastalert-kibana-plugin-1.1.0-${ELK_VERSION}.zip
\ No newline at end of file
diff --git a/elk-stack/kibana/config/kibana.yml b/elk-stack/kibana/config/kibana.yml
new file mode 100644
index 0000000..c80b6c0
--- /dev/null
+++ b/elk-stack/kibana/config/kibana.yml
@@ -0,0 +1,27 @@
+---
+## Default Kibana configuration from Kibana base image.
+## https://github.com/elastic/kibana/blob/master/src/dev/build/tasks/os_packages/docker_generator/templates/kibana_yml.template.js
+#
+server.name: kibana
+server.host: "0.0.0.0"
+
+# Elasticsearch Connection
+elasticsearch.hosts: [ "${ELASTICSEARCH_HOST_PORT}" ]
+
+# SSL settings
+server.ssl.enabled: true
+server.ssl.certificate: /certs/kibana.crt
+server.ssl.key: /certs/kibana.key
+server.ssl.certificateAuthorities: [ "/certs/ca.crt" ]
+xpack.security.encryptionKey: C1tHnfrlfxSPxPlQ8BlgPB5qMNRtg5V5
+xpack.encryptedSavedObjects.encryptionKey: D12GTfrlfxSPxPlGRBlgPB5qM5GOPDV5
+xpack.reporting.encryptionKey: RSCueeHKzrqzOVTJhkjt17EMnzM96LlN
+
+## X-Pack security credentials
+elasticsearch.username: ${ELASTIC_USERNAME}
+elasticsearch.password: ${ELASTIC_PASSWORD}
+elasticsearch.ssl.certificateAuthorities: [ "/certs/ca.crt" ]
+
+
+## Misc
+elasticsearch.requestTimeout: 90000
diff --git a/elk-stack/kibana/scripts/docker-healthcheck b/elk-stack/kibana/scripts/docker-healthcheck
new file mode 100644
index 0000000..3658d1a
--- /dev/null
+++ b/elk-stack/kibana/scripts/docker-healthcheck
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -eo pipefail
+
+host="$(hostname --ip-address || echo '127.0.0.1')"
+if health="$(curl -fsSkL "https://$ELASTIC_USERNAME:$ELASTIC_PASSWORD@$host:5601/api/status" | python -c "import sys, json; print json.load(sys.stdin)['status']['overall']['state']")"; then
+ health="$(echo "$health" | sed -r 's/^[[:space:]]+|[[:space:]]+$//g')" # trim whitespace (otherwise we'll have "green ")
+ if [ "$health" = 'green' ]; then
+ exit 0
+ fi
+ echo >&2 "unexpected health status: $health"
+fi
+exit 1
\ No newline at end of file
diff --git a/elk-stack/logstash/Dockerfile b/elk-stack/logstash/Dockerfile
new file mode 100644
index 0000000..a0b5879
--- /dev/null
+++ b/elk-stack/logstash/Dockerfile
@@ -0,0 +1,10 @@
+ARG ELK_VERSION
+
+# https://github.com/elastic/logstash-docker
+FROM docker.elastic.co/logstash/logstash:${ELK_VERSION}
+
+HEALTHCHECK --interval=240s --timeout=120s --retries=5 \
+ CMD curl -s -XGET 'http://127.0.0.1:9600'
+
+# Add your logstash plugins setup here
+RUN logstash-plugin install logstash-filter-grok
diff --git a/elk-stack/logstash/config/logstash.yml b/elk-stack/logstash/config/logstash.yml
new file mode 100644
index 0000000..43269c6
--- /dev/null
+++ b/elk-stack/logstash/config/logstash.yml
@@ -0,0 +1,9 @@
+---
+http.host: "0.0.0.0"
+xpack.monitoring.elasticsearch.hosts: [ "${ELASTICSEARCH_HOST_PORT}" ]
+
+## X-Pack security credentials
+xpack.monitoring.enabled: true
+xpack.monitoring.elasticsearch.username: ${ELASTIC_USERNAME}
+xpack.monitoring.elasticsearch.password: ${ELASTIC_PASSWORD}
+xpack.monitoring.elasticsearch.ssl.certificate_authority: /certs/ca.crt
diff --git a/elk-stack/logstash/config/pipelines.yml b/elk-stack/logstash/config/pipelines.yml
new file mode 100644
index 0000000..1adbc82
--- /dev/null
+++ b/elk-stack/logstash/config/pipelines.yml
@@ -0,0 +1,5 @@
+# For per pipeline config, check docs: https://www.elastic.co/guide/en/logstash/current/logstash-settings-file.html
+
+- pipeline.id: main
+ path.config: "/usr/share/logstash/pipeline/main.conf"
+ queue.type: memory
diff --git a/elk-stack/logstash/pipeline/main.conf b/elk-stack/logstash/pipeline/main.conf
new file mode 100644
index 0000000..6afcf32
--- /dev/null
+++ b/elk-stack/logstash/pipeline/main.conf
@@ -0,0 +1,33 @@
+input {
+ tcp {
+ port => 5000
+ codec => json_lines
+ }
+}
+
+filter {
+ grok {
+ patterns_dir => ["/usr/share/logstash/pipeline/patterns"]
+ match => {
+ "message" =>
+ "Pipeline: %{NUMBER:pipelineID:int} Browser: %{BROWSER:browser} Status: %{STATUS:status} Test: %{WORD:test} Suite: %{WORD:suite}( Trace: %{GREEDYDATA:trace})?"
+ }
+ }
+
+ if "_grokparsefailure" in [tags] {
+ drop { }
+ }
+}
+
+output {
+ elasticsearch {
+ index => "e2e"
+ document_type => "log"
+ hosts => [ "${ELASTICSEARCH_HOST_PORT}" ]
+ user => "${ELASTIC_USERNAME}"
+ password => "${ELASTIC_PASSWORD}"
+ ssl => true
+ ssl_certificate_verification => false
+ cacert => '/certs/ca.crt'
+ }
+}
diff --git a/elk-stack/logstash/pipeline/patterns/browser b/elk-stack/logstash/pipeline/patterns/browser
new file mode 100644
index 0000000..4ead552
--- /dev/null
+++ b/elk-stack/logstash/pipeline/patterns/browser
@@ -0,0 +1 @@
+BROWSER \b(chrome|firefox|safari)\b
diff --git a/elk-stack/logstash/pipeline/patterns/status b/elk-stack/logstash/pipeline/patterns/status
new file mode 100644
index 0000000..4e3e6d7
--- /dev/null
+++ b/elk-stack/logstash/pipeline/patterns/status
@@ -0,0 +1 @@
+STATUS \b(failed|skipped|passed)\b
diff --git a/elk-stack/setup/instances.yml b/elk-stack/setup/instances.yml
new file mode 100644
index 0000000..2025ecb
--- /dev/null
+++ b/elk-stack/setup/instances.yml
@@ -0,0 +1,14 @@
+instances:
+ - name: elasticsearch
+ dns:
+ - elasticsearch
+ - localhost
+ ip:
+ - 127.0.0.1
+
+ - name: kibana
+ dns:
+ - kibana
+ - localhost
+ ip:
+ - 127.0.0.1
\ No newline at end of file
diff --git a/elk-stack/setup/keystore.sh b/elk-stack/setup/keystore.sh
new file mode 100644
index 0000000..224c397
--- /dev/null
+++ b/elk-stack/setup/keystore.sh
@@ -0,0 +1,27 @@
+# Exit on Error
+set -e
+
+# Setting Bootstrap Password
+echo "Setting bootstrap.password..."
+(echo "$ELASTIC_PASSWORD" | elasticsearch-keystore add -x 'bootstrap.password')
+
+# ----- Setting Secrets
+
+## Add Additional Config
+# 1- Copy the below commented block, uncomment it, and replace , , and .
+# 2- Pass to setup container in `docker-compose-setup.yml`
+
+## Setting
+#echo "Setting ..."
+#(echo "$" | elasticsearch-keystore add -x '')
+
+
+# ----- Setting S3 Secrets
+
+## Setting S3 Access Key
+#echo "Setting S3 Access Key..."
+#(echo "$AWS_ACCESS_KEY_ID" | elasticsearch-keystore add -x 's3.client.default.access_key')
+#
+## Setting S3 Secret Key
+#echo "Setting S3 Secret Key..."
+#(echo "$AWS_SECRET_ACCESS_KEY" | elasticsearch-keystore add -x 's3.client.default.secret_key')
\ No newline at end of file
diff --git a/elk-stack/setup/setup-certs.sh b/elk-stack/setup/setup-certs.sh
new file mode 100644
index 0000000..4d5626f
--- /dev/null
+++ b/elk-stack/setup/setup-certs.sh
@@ -0,0 +1,31 @@
+# Exit on Error
+set -e
+
+OUTPUT_DIR=/secrets/certs
+ZIP_FILE=$OUTPUT_DIR/certs.zip
+
+printf "======= Generating Elastic Stack Certificates =======\n"
+printf "=====================================================\n"
+
+if ! command -v unzip &>/dev/null; then
+ printf "Installing Necessary Tools... \n"
+ yum install -y -q -e 0 unzip;
+fi
+
+printf "Clearing Old Certificates if exits... \n"
+find $OUTPUT_DIR -mindepth 1 -type d -exec rm -rf -- {} +
+rm -f $ZIP_FILE
+
+printf "Generating... \n"
+bin/elasticsearch-certutil cert --silent --pem --in /setup/instances.yml -out $ZIP_FILE &> /dev/null
+
+printf "Unzipping Certifications... \n"
+unzip -qq $ZIP_FILE -d $OUTPUT_DIR;
+
+printf "Applying Permissions... \n"
+chown -R 1000:0 $OUTPUT_DIR
+find $OUTPUT_DIR -type f -exec chmod 655 -- {} +
+
+printf "=====================================================\n"
+printf "SSL Certifications generation completed successfully.\n"
+printf "=====================================================\n"
diff --git a/elk-stack/setup/setup-keystore.sh b/elk-stack/setup/setup-keystore.sh
new file mode 100644
index 0000000..b241479
--- /dev/null
+++ b/elk-stack/setup/setup-keystore.sh
@@ -0,0 +1,36 @@
+# Exit on Error
+set -e
+
+OUTPUT_FILE=/secrets/keystore/elasticsearch.keystore
+NATIVE_FILE=/usr/share/elasticsearch/config/elasticsearch.keystore
+
+# Password Generate
+PW=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16 ;)
+ELASTIC_PASSWORD="${ELASTIC_PASSWORD:-$PW}"
+export ELASTIC_PASSWORD
+
+# Create Keystore
+printf "========== Creating Elasticsearch Keystore ==========\n"
+printf "=====================================================\n"
+elasticsearch-keystore create >> /dev/null
+
+# Setting Secrets
+echo "Elastic password is: $ELASTIC_PASSWORD"
+sh /setup/keystore.sh
+
+# Replace current Keystore
+if [ -f "$OUTPUT_FILE" ]; then
+ echo "Remove old elasticsearch.keystore"
+ rm $OUTPUT_FILE
+fi
+
+echo "Saving new elasticsearch.keystore"
+mv $NATIVE_FILE $OUTPUT_FILE
+chmod 0644 $OUTPUT_FILE
+
+printf "======= Keystore setup completed successfully =======\n"
+printf "=====================================================\n"
+printf "Remember to restart the stack, or reload secure settings if changed settings are hot-reloadable.\n"
+printf "About Reloading Settings: https://www.elastic.co/guide/en/elasticsearch/reference/current/secure-settings.html#reloadable-secure-settings\n"
+printf "Your 'elastic' user password is: $ELASTIC_PASSWORD\n"
+printf "=====================================================\n"
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 3a4d020..5d768c0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,19 +5,36 @@
4.0.0
awesome.group.id
- ui-automation-bootstrap
+ test-automation-bootstrap
1.0.0-SNAPSHOT
jar
- ui-automation-bootstrap
- A template for selenium based ui automation projects using selenide
- https://github.com/sergiomartins8/ui-automation-bootstrap
+ test-automation-bootstrap
+ A template to jumpstart test automation frameworks
+ https://github.com/sergiomartins8/test-automation-bootstrap
-
- suiteA
UTF-8
UTF-8
+ 11
+
+
+ suiteA
+
+
+
+
+ 5.16.2
+ 7.1.0
+ 2.22.2
+ 3.8.1
+ 3.1.1
+ 6.4
+ 1.2.3
+ 4.0.6
+ 2.1.1
+ 2.11.1
+ 1.18.16
@@ -25,16 +42,16 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.8.1
+ ${maven.compiler.plugin}
-
- 11
+
+ ${java.version}
org.apache.maven.plugins
maven-surefire-plugin
- 2.22.2
+ ${maven.surefire.plugin}
@@ -43,7 +60,7 @@
threadCount
- ${threadCount}
+ ${thread.count}
listener
@@ -58,7 +75,7 @@
org.apache.maven.plugins
maven-checkstyle-plugin
- 3.1.1
+ ${maven.checkstyle.plugin}
src/test/resources/checkstyle/checkstyle.xml
@@ -82,41 +99,46 @@
+
+ net.logstash.logback
+ logstash-logback-encoder
+ ${logstash.logback.encoder}
+
ch.qos.logback
logback-classic
- 1.2.3
+ ${logback.classic}
com.codeborne
selenide
- 5.15.0
+ ${selenide.version}
org.testng
testng
- 7.1.0
+ ${testng.version}
com.aventstack
extentreports
- 4.0.6
+ ${extent.reports}
com.browserup
browserup-proxy-core
- 2.1.1
+ ${browserup.proxy.core}
com.fasterxml.jackson.core
jackson-annotations
- 2.11.1
+ ${jackson.annotations}
org.projectlombok
lombok
true
- 1.18.10
+ ${lombok.version}
diff --git a/src/test/java/io/company/pageobjects/components/SearchComponent.java b/src/test/java/io/company/pageobjects/components/SearchComponent.java
index 780b889..4f82e04 100644
--- a/src/test/java/io/company/pageobjects/components/SearchComponent.java
+++ b/src/test/java/io/company/pageobjects/components/SearchComponent.java
@@ -1,5 +1,6 @@
package io.company.pageobjects.components;
+import io.company.pageobjects.pages.GoogleResultsPage;
import org.openqa.selenium.Keys;
public class SearchComponent extends BaseComponent {
@@ -7,8 +8,8 @@ public SearchComponent(String selector) {
super(selector);
}
- public SearchComponent searchFor(String word) {
+ public GoogleResultsPage searchFor(String word) {
self().sendKeys(word, Keys.ENTER);
- return this;
+ return new GoogleResultsPage();
}
}
diff --git a/src/test/java/io/company/tests/examples/ExampleMockedTest.java b/src/test/java/io/company/tests/examples/ExampleMockedTest.java
index fb6ff60..af5b897 100644
--- a/src/test/java/io/company/tests/examples/ExampleMockedTest.java
+++ b/src/test/java/io/company/tests/examples/ExampleMockedTest.java
@@ -8,6 +8,12 @@
import static com.codeborne.selenide.Selenide.open;
+/**
+ * Use @Listeners(...) in order to execute the tests with mocked responses from the @Mock annotation "clazz".
+ *
+ * On the other hand, simply execute the tests by passing the listener maven property (check the documentation).
+ **/
+//@Listeners(MockListener.class)
public class ExampleMockedTest extends BaseTest {
@BeforeMethod
diff --git a/src/test/java/io/company/tests/examples/GoogleSearchTest.java b/src/test/java/io/company/tests/examples/GoogleSearchTest.java
index 8f7e2a2..f46d19c 100644
--- a/src/test/java/io/company/tests/examples/GoogleSearchTest.java
+++ b/src/test/java/io/company/tests/examples/GoogleSearchTest.java
@@ -32,13 +32,11 @@ public void teardown() {
@Test(description = "Open up a google page and search for the word 'dogs'")
public void shouldPerformSearch() {
- open("http://google.com");
+ open("https://google.com");
googleSearchPage
.searchComponent()
- .searchFor("dogs");
-
- googleResultsPage
+ .searchFor("dogs")
.searchComponent()
.self()
.shouldHave(value("dogs"));
@@ -46,7 +44,7 @@ public void shouldPerformSearch() {
@Test
public void shouldSearchResultsBeDisplayed() {
- open("http://www.google.pt/search?source=hp&q=dogs&oq=dogs");
+ open("https://www.google.pt/search?source=hp&q=dogs&oq=dogs");
googleResultsPage
.getResults()
diff --git a/src/test/java/io/company/utils/config/CustomConfiguration.java b/src/test/java/io/company/utils/config/CustomConfiguration.java
index 304f468..e9ac7ad 100644
--- a/src/test/java/io/company/utils/config/CustomConfiguration.java
+++ b/src/test/java/io/company/utils/config/CustomConfiguration.java
@@ -28,4 +28,14 @@ private CustomConfiguration() {
* Default value: null (Custom configuration is not set)
*/
public static String exampleConfiguration = DEFAULTS.exampleConfiguration();
+
+ /**
+ * The pipeline ID for the current execution.
+ * Can be configured either programmatically or by environment variable.
+ *
+ * EXAMPLE: "export CI_PIPELINE_IID=9000"
+ * abr>
+ * Default value: null (environment variable not defined).
+ */
+ public static int pipelineID = DEFAULTS.pipelineID();
}
diff --git a/src/test/java/io/company/utils/config/CustomConfigurationHolder.java b/src/test/java/io/company/utils/config/CustomConfigurationHolder.java
index 62945b5..694e18e 100644
--- a/src/test/java/io/company/utils/config/CustomConfigurationHolder.java
+++ b/src/test/java/io/company/utils/config/CustomConfigurationHolder.java
@@ -4,9 +4,15 @@
public class CustomConfigurationHolder implements Loggable {
private final String customConfiguration = System.getProperty("custom.configuration");
+ private final int pipelineID = System.getenv("CI_PIPELINE_ID") == null
+ ? -1 : Integer.parseInt(System.getenv("CI_PIPELINE_ID"));
public String exampleConfiguration() {
logger().info("Custom config: " + customConfiguration);
return customConfiguration;
}
+
+ public int pipelineID() {
+ return pipelineID;
+ }
}
diff --git a/src/test/java/io/company/utils/listeners/DistributedReportListener.java b/src/test/java/io/company/utils/listeners/DistributedReportListener.java
new file mode 100644
index 0000000..f80b085
--- /dev/null
+++ b/src/test/java/io/company/utils/listeners/DistributedReportListener.java
@@ -0,0 +1,29 @@
+package io.company.utils.listeners;
+
+import com.codeborne.selenide.Configuration;
+import io.company.utils.config.CustomConfiguration;
+import io.company.utils.logging.Loggable;
+import org.testng.ITestListener;
+import org.testng.ITestResult;
+
+public class DistributedReportListener implements ITestListener, Loggable {
+
+ @Override
+ public void onTestSuccess(ITestResult iTestResult) {
+ logger().info("Pipeline: {} Browser: {} Status: {} Test: {} Suite: {}",
+ CustomConfiguration.pipelineID, Configuration.browser, "passed", iTestResult.getName(), System.getProperty("suite"));
+ }
+
+ @Override
+ public void onTestFailure(ITestResult iTestResult) {
+ logger().error("Pipeline: {} Browser: {} Status: {} Test: {} Suite: {} Trace: {}",
+ CustomConfiguration.pipelineID, Configuration.browser, "failed", iTestResult.getName(), System.getProperty("suite"),
+ iTestResult.getThrowable().getMessage());
+ }
+
+ @Override
+ public void onTestSkipped(ITestResult iTestResult) {
+ logger().info("Pipeline: {} Browser: {} Status: {} Test: {} Suite: {}",
+ CustomConfiguration.pipelineID, Configuration.browser, "skipped", iTestResult.getName(), System.getProperty("suite"));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/io/company/utils/reports/ExtentManager.java b/src/test/java/io/company/utils/reports/ExtentManager.java
index 5436492..d0e4494 100644
--- a/src/test/java/io/company/utils/reports/ExtentManager.java
+++ b/src/test/java/io/company/utils/reports/ExtentManager.java
@@ -30,7 +30,7 @@ public static synchronized ExtentReports getInstance() {
extentReports.attachReporter(htmlReporter);
// General information related to application
- extentReports.setSystemInfo("Application Name", "ui automation bootstrap");
+ extentReports.setSystemInfo("Application Name", "test automation bootstrap");
extentReports.setSystemInfo("User Name", "http://github.com/sergiomartins8");
extentReports.setSystemInfo("Environment", "Production");
}
diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml
index f622044..66b2487 100644
--- a/src/test/resources/logback.xml
+++ b/src/test/resources/logback.xml
@@ -1,11 +1,20 @@
-
-
-
-
- %green(%d{yyyy-MM-dd HH:mm:ss.SSS}) %magenta([%thread]) %highlight(%-5level) %yellow(%logger{36}) - %msg%n
-
-
-
-
-
-
+
+
+
+
+ %green(%d{yyyy-MM-dd HH:mm:ss.SSS}) %magenta([%thread]) %highlight(%-5level) %yellow(%logger{36}) - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+