Repository navigation
Expand file tree
/
Copy pathTestNgFeaturesTest.java
More file actions
157 lines (140 loc) · 7.04 KB
/
Copy pathTestNgFeaturesTest.java
File metadata and controls
157 lines (140 loc) · 7.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Package of the test classes
package com.automation.selenium.tests;
// TestNG hard assertions: the first failing one stops the test
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
// Default value for a suite parameter when testng.xml does not set it
import org.testng.annotations.Optional;
// Takes a method parameter's value from a <parameter> in testng.xml
import org.testng.annotations.Parameters;
// Marks a method (or every public method of a class) as a TestNG test
import org.testng.annotations.Test;
// Soft assertions: collect failures and report them all at the end
import org.testng.asserts.SoftAssert;
// Base class: starts a browser before each test and closes it afterwards
import com.automation.selenium.base.BaseTest;
// Retry analyzer that runs a failed test once more
import com.automation.selenium.base.RetryOnce;
// Settings (user name, password, ...)
import com.automation.selenium.config.Config;
// Page object of the login page
import com.automation.selenium.pages.LoginPage;
// Writes steps into the HTML report
import com.automation.selenium.utils.Steps;
/**
* TestNG features that interviews ask about, each used on a real OrangeHRM
* check: soft assertions, expected exceptions, priority with
* dependsOnMethods, invocationCount, timeOut, a retry analyzer and suite
* parameters. Data providers and groups are shown in LoginTest; a skip and a
* failed dependency in ReportDemoTest.
*/
// Every test in this class belongs to the "interview" group
@Test(groups = "interview")
public class TestNgFeaturesTest extends BaseTest {
// Title of every OrangeHRM page
private static final String TITLE = "OrangeHRM";
/**
* SoftAssert: checks four things on the login page and reports every
* mismatch together, instead of stopping at the first one. assertAll()
* at the end is what fails the test; without it the failures are lost.
*/
@Test(description = "[TC-121] TestNG: SoftAssert checks the whole login page in one run")
public void tc121_softAssertChecksTheLoginPage() {
// Open the login page
LoginPage login = openLoginPage();
// A new SoftAssert per test: it remembers every failed check
SoftAssert soft = new SoftAssert();
// Each check records a failure but lets the test go on
soft.assertEquals(driver().getTitle(), TITLE, "Page title");
soft.assertEquals(login.placeholder("Username"), "Username", "Username placeholder");
soft.assertEquals(login.placeholder("Password"), "Password", "Password placeholder");
soft.assertEquals(login.buttonText(), "Login", "Button text");
// Record in the report what was checked
Steps.log("Checked title, both placeholders and the button text");
// Now fail the test if any check above failed, listing all of them in one error
soft.assertAll();
}
/**
* expectedExceptions: the test passes only if it throws an
* IllegalStateException whose message matches the pattern. loginAs()
* throws exactly that when the site shows "Invalid credentials".
*/
// The test passes only if this exception type is thrown and its message matches the regex
@Test(expectedExceptions = IllegalStateException.class, expectedExceptionsMessageRegExp = ".*Invalid credentials.*",
description = "[TC-102] TestNG: expectedExceptions, a wrong password must stop with the login error")
public void tc102_wrongPasswordThrowsTheLoginError() {
// Right user, wrong password: loginAs throws "Login as "Admin" failed: Invalid credentials"
openLoginPage().loginAs(Config.get().username(), "wrong-password");
}
/**
* priority: the lower number runs first within this class (the default is
* 0), so this check runs before the dependent test below.
*/
@Test(priority = 1, description = "[TC-121] TestNG: priority, the login page check runs first")
public void tc121_loginPageIsShown() {
// Open the login page and check its form is there
assertTrue(openLoginPage().isDisplayed(), "The login form should be shown");
}
/**
* dependsOnMethods: runs only if tc121_loginPageIsShown passed. Had it failed,
* TestNG would skip this test, not fail it (see ReportDemoTest).
*/
@Test(priority = 2, dependsOnMethods = "tc121_loginPageIsShown",
description = "[TC-101] TestNG: dependsOnMethods, log in only after the login page check passed")
public void tc101_adminLogsInAfterThePageCheck() {
// Log in and check the dashboard
assertTrue(loginAsAdmin().isDisplayed(), "The dashboard should be shown");
}
/**
* invocationCount: TestNG runs this test twice, each run with its own
* browser, and reports each run. Useful to catch a check that only
* sometimes passes.
*/
@Test(invocationCount = 2, description = "[TC-102] TestNG: invocationCount, a wrong password is rejected every time")
public void tc102_wrongPasswordIsRejectedEveryTime() {
// Submit a wrong password (submit does not expect the login to work)
LoginPage login = openLoginPage().submit(Config.get().username(), "wrong-password");
// The red banner must say "Invalid credentials" on every run
assertEquals(login.errorMessage(), "Invalid credentials", "Error banner");
}
/**
* timeOut: fails the test if it runs longer than 60 seconds. It is a safety
* net against a page that hangs; the explicit waits still give the precise
* error for anything slower than expected. The timed test still sees the
* browser that BaseTest started for this thread.
*/
// 60_000 ms = 60 s (the underscore is only a digit separator for readability)
@Test(timeOut = 60_000, description = "[TC-122] TestNG: timeOut, the login must finish within 60 seconds")
public void tc122_loginFinishesWithinOneMinute() {
// Log in and check the dashboard, all within the time limit
assertTrue(loginAsAdmin().isDisplayed(), "The dashboard should be shown");
}
/**
* retryAnalyzer: if this test fails, RetryOnce runs it one more time
* before it counts as failed, which covers a short outage of the demo
* site. A passing run is never retried.
*/
@Test(retryAnalyzer = RetryOnce.class, description = "[TC-101] TestNG: retryAnalyzer, retried once if the demo site has a hiccup")
public void tc101_adminLoginIsRetriedOnceOnFailure() {
// Log in and check the dashboard; on failure TestNG asks RetryOnce whether to run again
assertTrue(loginAsAdmin().isDisplayed(), "The dashboard should be shown");
}
/**
* Parameters: the value comes from testng.xml
* ({@code <parameter name="expectedTitle" .../>}). Maven runs the classes
* without that file, so Optional supplies the default.
*
* @param expectedTitle the page title the suite expects.
*/
// Fill the method parameter from <parameter name="expectedTitle"> in testng.xml
@Parameters("expectedTitle")
@Test(description = "[TC-121] TestNG: Parameters from testng.xml, with an Optional default")
public void tc121_titleMatchesTheSuiteParameter(@Optional(TITLE) String expectedTitle) {
// Open the login page
openLoginPage();
// Show in the report which value was used (from testng.xml or the default)
Steps.log("Expected title from the suite: \"" + expectedTitle + "\"");
// The browser tab title must match
assertEquals(driver().getTitle(), expectedTitle, "Page title");
}
}