Skip to content

Commit fc8d508

Browse files
committed
feat: initial e2e test framework for QACart Todo
This initial commit includes the full implementation (~85%) of a Java-based test automation framework for testing the QACart Todo web application. Key components: - Selenium WebDriver + Java + TestNG for UI test automation - REST Assured for API test coverage - Page Object Model (POM) structure for maintainable UI tests - Fluent-style page methods for readable test scripts - Singleton-based ConfigUtil for environment config - Thread-safe WebDriver handling using ThreadLocal - Allure integration for rich, visual test reports - Maven structure with support for profiles - Base test hooks and reusable assertion utilities - Hybrid testing approach covering both UI and API flows This version includes working tests for: - Login - Signup - Adding and deleting todos (via UI + API)
0 parents  commit fc8d508

File tree

30 files changed

+1327
-0
lines changed

30 files changed

+1327
-0
lines changed

.github/workflows/main.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Run Selenium Test
2+
on:
3+
push:
4+
branches: [ "master" ]
5+
6+
jobs:
7+
test:
8+
runs-on: windows-latest
9+
steps:
10+
- uses: actions/checkout@v3
11+
- uses: actions/setup-java@v3
12+
with:
13+
java-version: '21'
14+
cache: maven
15+
distribution: 'temurin'
16+
- uses: browser-actions/setup-chrome@latest
17+
- run: mvn clean test

.gitignore

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
target/
2+
!.mvn/wrapper/maven-wrapper.jar
3+
!**/src/main/**/target/
4+
!**/src/test/**/target/
5+
6+
### IntelliJ IDEA ###
7+
.idea/modules.xml
8+
.idea/jarRepositories.xml
9+
.idea/compiler.xml
10+
.idea/libraries/
11+
*.iws
12+
*.iml
13+
*.ipr
14+
15+
### Eclipse ###
16+
.apt_generated
17+
.classpath
18+
.factorypath
19+
.project
20+
.settings
21+
.springBeans
22+
.sts4-cache
23+
24+
### NetBeans ###
25+
/nbproject/private/
26+
/nbbuild/
27+
/dist/
28+
/nbdist/
29+
/.nb-gradle/
30+
build/
31+
!**/src/main/**/build/
32+
!**/src/test/**/build/
33+
34+
### VS Code ###
35+
.vscode/
36+
37+
### Mac OS ###
38+
.DS_Store

.idea/.gitignore

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/encodings.xml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pom.xml

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.omarelsheikh.todo</groupId>
8+
<artifactId>todo-app-qa-task</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<properties>
12+
<maven.compiler.source>21</maven.compiler.source>
13+
<maven.compiler.target>21</maven.compiler.target>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
</properties>
16+
17+
<build>
18+
<plugins>
19+
<plugin>
20+
<groupId>org.apache.maven.plugins</groupId>
21+
<artifactId>maven-surefire-plugin</artifactId>
22+
<version>3.5.3</version>
23+
<configuration>
24+
<argLine>
25+
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/1.9.24/aspectjweaver-1.9.24.jar"
26+
</argLine>
27+
<parallel>methods</parallel>
28+
<threadCount>3</threadCount>
29+
</configuration>
30+
<dependencies>
31+
<dependency>
32+
<groupId>org.aspectj</groupId>
33+
<artifactId>aspectjweaver</artifactId>
34+
<version>1.9.24</version>
35+
</dependency>
36+
</dependencies>
37+
</plugin>
38+
</plugins>
39+
</build>
40+
41+
<dependencies>
42+
43+
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
44+
<dependency>
45+
<groupId>org.seleniumhq.selenium</groupId>
46+
<artifactId>selenium-java</artifactId>
47+
<version>4.34.0</version>
48+
</dependency>
49+
50+
<!-- https://mvnrepository.com/artifact/org.testng/testng -->
51+
<dependency>
52+
<groupId>org.testng</groupId>
53+
<artifactId>testng</artifactId>
54+
<version>7.11.0</version>
55+
<scope>test</scope>
56+
</dependency>
57+
58+
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
59+
<dependency>
60+
<groupId>org.slf4j</groupId>
61+
<artifactId>slf4j-api</artifactId>
62+
<version>2.0.17</version>
63+
</dependency>
64+
65+
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
66+
<dependency>
67+
<groupId>org.apache.logging.log4j</groupId>
68+
<artifactId>log4j-api</artifactId>
69+
<version>2.25.0</version>
70+
</dependency>
71+
72+
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
73+
<dependency>
74+
<groupId>org.apache.logging.log4j</groupId>
75+
<artifactId>log4j-core</artifactId>
76+
<version>2.25.0</version>
77+
</dependency>
78+
79+
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j2-impl -->
80+
<dependency>
81+
<groupId>org.apache.logging.log4j</groupId>
82+
<artifactId>log4j-slf4j2-impl</artifactId>
83+
<version>2.25.0</version>
84+
<scope>compile</scope>
85+
</dependency>
86+
87+
<!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
88+
<dependency>
89+
<groupId>io.rest-assured</groupId>
90+
<artifactId>rest-assured</artifactId>
91+
<version>5.5.5</version>
92+
<scope>test</scope>
93+
</dependency>
94+
95+
<!-- https://mvnrepository.com/artifact/com.github.javafaker/javafaker -->
96+
<dependency>
97+
<groupId>com.github.javafaker</groupId>
98+
<artifactId>javafaker</artifactId>
99+
<version>1.0.2</version>
100+
</dependency>
101+
102+
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
103+
<dependency>
104+
<groupId>com.fasterxml.jackson.core</groupId>
105+
<artifactId>jackson-databind</artifactId>
106+
<version>2.19.2</version>
107+
</dependency>
108+
109+
<!-- https://mvnrepository.com/artifact/io.qameta.allure/allure-testng -->
110+
<dependency>
111+
<groupId>io.qameta.allure</groupId>
112+
<artifactId>allure-testng</artifactId>
113+
<version>2.29.1</version>
114+
</dependency>
115+
116+
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
117+
<dependency>
118+
<groupId>commons-io</groupId>
119+
<artifactId>commons-io</artifactId>
120+
<version>2.20.0</version>
121+
</dependency>
122+
123+
</dependencies>
124+
125+
</project>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.omarelsheikh.todo.api.config;
2+
3+
public class EndPoints {
4+
5+
public static final String API_REGISTER_END_POINT = "/api/v1/users/register";
6+
public static final String API_TASK_END_POINT = "api/v1/tasks";
7+
public static final String TODO_END_POINT = "/todo";
8+
public static final String NEW_TODO_END_POINT = "/todo/new";
9+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.omarelsheikh.todo.api.models;
2+
3+
/**
4+
* Represents the structure of a Todo item as expected by the backend API.
5+
* Only includes fields allowed by the API contract.
6+
*/
7+
public class Todo {
8+
9+
private boolean isCompleted;
10+
private String item;
11+
12+
public Todo(String item, boolean isCompleted) {
13+
this.item = item;
14+
this.isCompleted = isCompleted;
15+
}
16+
17+
public boolean getIsCompleted() {
18+
return isCompleted;
19+
}
20+
21+
public void setIsCompleted(boolean isCompleted) {
22+
this.isCompleted = isCompleted;
23+
}
24+
25+
public String getItem() {
26+
return item;
27+
}
28+
29+
public void setItem(String item) {
30+
this.item = item;
31+
}
32+
33+
34+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.omarelsheikh.todo.drivers;
2+
3+
import org.openqa.selenium.WebDriver;
4+
import org.openqa.selenium.chrome.ChromeDriver;
5+
import org.openqa.selenium.edge.EdgeDriver;
6+
import org.openqa.selenium.firefox.FirefoxDriver;
7+
8+
import java.time.Duration;
9+
10+
/**
11+
* Factory class to initialize and configure the WebDriver instance
12+
* based on the browser specified via system property.
13+
*/
14+
public class DriverFactory {
15+
16+
// Instance variable to hold the WebDriver object
17+
private WebDriver driver;
18+
19+
public WebDriver initializeDriver() {
20+
21+
// Read browser name from system properties, default to "CHROME"
22+
String browser = System.getProperty("browser", "CHROME").toUpperCase();
23+
24+
// Switch based on browser name
25+
switch (browser) {
26+
case "CHROME":
27+
driver = new ChromeDriver();
28+
break;
29+
case "FIREFOX":
30+
driver = new FirefoxDriver();
31+
break;
32+
case "EDGE":
33+
driver = new EdgeDriver();
34+
break;
35+
default:
36+
throw new RuntimeException("Browser not supported: " + browser);
37+
}
38+
39+
// Basic configurations for the WebDriver
40+
driver.manage().window().maximize();
41+
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
42+
return driver;
43+
}
44+
}

0 commit comments

Comments
 (0)