[remote "upstream"]
url = https://github.com/olegsher2022/telran.git
fetch = +refs/heads/*:refs/remotes/upstream/*
basic commands:
git fetch --all
daily:
git rebase upstream main
git pull upstream main
git push origin main
Jenkins.pptx
Jenkins Triger_git_each15Min.pdf
Works with Java 11 only
java8.bat - for windows only
java11.bat - for windows only
java17.bat - for windows only
java21.bat - for windows only
- refactoring deprecated EventFiringWebDriver with EventFiringDecorator
- refactoring WDListener.java using
implements WebDriverListener
- add additional browsers (chrome, firefox, safary etc)
- add run per environment (production, staging, dev)
- add run per test groups (smoke, regression, sanity)
- read data from file
- ● WebDriver Listeners
- ● TestNG Listeners
Практическое использование Listeners в Selenium Automation Testing может
заключаться в регистрации порядка действий и создании снимка экрана при
возникновении исключения. Это облегчает отладку на более поздних этапах
выполнения теста.
- Add testNG listener procedure
All about TestNG Listeners in Selenium
- create class TestNGListener.java in manager
- add
public class TestNGListener implements ITestListener
- add
Logger logger = LoggerFactory.getLogger(TestNGListener.class);
- override all methods
Реализацию можно описать в три шага:
1.Создать class MyListener extends AbstractWebDriverEventListener
2.Создать Constructor super class
3.Переопределить нужные методы (аннотация @Override)
WDListener.java
2. create public class WDListener extends AbstractWebDriverEventListener {
3. add Logger logger = LoggerFactory.getLogger(TestNGListener.class);
4. create empty constructor public WDListener() {super(); }
4. override all methods
5. changes in ApplicationManager.java
6. EventFiringWebDriver driver;
7. driver = new EventFiringWebDriver(new ChromeDriver());
8. driver.register(new WDListener());
- Screenshots
-
create folder screenshots in test
-
add code
@Override public void onException(Throwable throwable, WebDriver driver) { super.onException(throwable, driver); logger.error("start on exception in wdlistener driver"); String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime()); String fileName = "src/test/screenshots/screenshot-" + timeStamp + ".png"; logger.info("created screenshot " + fileName); takeScreenshot((TakesScreenshot) driver, fileName); }
private void takeScreenshot(TakesScreenshot takesScreenshot, String fileName){ try{ File tmp = takesScreenshot.getScreenshotAs(OutputType.FILE); File screenshot = new File(fileName); Files.copy(tmp,screenshot); } catch (IOException e){ e.printStackTrace(); logger.error(e.getMessage()); } }```
-
Run tests from console(Linux)
- check build.gradle for
task reg(type: Test){
useTestNG {
def suite = System.getProperty('suite', '')
if (suite.equals('quick')) {
suites 'src/test/resources/quick.xml'
} else if (suite.equals('smoke')) {
suites 'src/test/resources/smoke.xml'
} else {
suites 'src/test/resources/testng.xml'
}
if (project.hasProperty('browser')) {
systemProperty 'browser', "${browser}"
}
}
}
- have testng.xml in src/test/resources/ testng.xml
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="ilCarro">
<test name="LoginTests">
<classes>
<class name="tests.LoginTests"/>
</classes>
</test>
<test name="RegistrationTests">
<classes>
<class name="tests.RegistrationTests"/>
</classes>
</test>
</suite>
run from console:
gradle reg
after test suite finished check for:
olegsher@olegsher:~/workspace/telran (lesson_15)$ gradle reg
:compileJava UP-TO-DATE
:processResources NO-SOURCE
:classes UP-TO-DATE
:compileTestJavaNote: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
:processTestResources UP-TO-DATE
:testClasses
:reg
ilCarro > LoginTests > tests.LoginTests.positiveLogin1 FAILED
org.openqa.selenium.ElementNotInteractableException at LoginTests.java:55
tests.LoginTests.postconditionsLogin FAILED
org.openqa.selenium.JavascriptException at LoginTests.java:22
ilCarro > RegistrationTests > tests.RegistrationTests.negativeRegistrationWrongEmail FAILED
org.openqa.selenium.interactions.MoveTargetOutOfBoundsException at RegistrationTests.java:54
ilCarro > RegistrationTests > tests.RegistrationTests.negativeRegistrationWrongPassword FAILED
org.openqa.selenium.interactions.MoveTargetOutOfBoundsException at RegistrationTests.java:74
ilCarro > RegistrationTests > tests.RegistrationTests.positiveRegistration FAILED
org.openqa.selenium.interactions.MoveTargetOutOfBoundsException at RegistrationTests.java:34
12 tests completed, 5 failed, 5 skipped
:reg FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':reg'.
> There were failing tests. See the report at: file:///home/olegsher/workspace/telran/build/reports/tests/reg/index.html
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 28s
4 actionable tasks: 2 executed, 2 up-to-date
and run:
firefox file:///home/olegsher/workspace/telran/build/reports/tests/reg/index.html
- Alerts on page
HTML Window alert() method is used to display an alert box.
It displays a specified message along with an OK button and is generally used to make sure that the information comes through the user.
It returns a string that represents the text to display in the alert box.
<button ondblclick="myalert()">
Show Alert Message
</button>
<script>
function myalert() {
alert("Welcome to GeeksforGeeks.\n " +
"It is the best portal for computer" +
"science enthusiasts!");
}
</script>
HTML DOM Window alert() Method
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
The simplest of these is referred to as an alert, which shows a custom message, and a single button which dismisses the alert, labelled in most browsers as OK. It can also be dismissed in most browsers by pressing the close button, but this will always do the same thing as the OK button.
WebDriver can get the text from the popup and accept or dismiss these alerts.
String text = alert.getText();
alert.accept();
- Confirm
A confirm box is similar to an alert, except the user can also choose to cancel the message
//Wait for the alert to be displayed
wait.until(ExpectedConditions.alertIsPresent());
//Store the alert in a variable
Alert alert = driver.switchTo().alert();
//Store the alert in a variable for reuse
String text = alert.getText();
//Press the Cancel button
alert.dismiss();
- Prompt
Prompts are similar to confirm boxes, except they also include a text input. Similar to working with form elements, you can use WebDriver’s send keys to fill in a response.
This will completely replace the placeholder text.
//Wait for the alert to be displayed and store it in a variable
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
//Type your message
alert.sendKeys("Selenium");
//Press the OK button
alert.accept();
- issue - if user already logged in - should be logout
- add xpath for log out button
By btnLogout = By.xpath("//a[contains(@href, 'logout')]");
- add method to BaseHelper to check if element is available
public boolean isElementExist(By locator) {
return findElementsBase(locator).size() > 0;
}
- add boolean method to check if we already loggedin
public boolean btnLogoutExist() {
return isElementExist(btnLogout);
}
public void logoutIflogin() {
if (app.getUserHelper().btnLogoutExist()) {
app.getUserHelper().logout();
}
}
public void logout() {
clickBase(btnLogout);
}
- Logger intro
add to build.gradle
implementation 'ch.qos.logback:logback-classic:1.3.5'
add configuration file logback.xml
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.baeldung.logback.tests" level="WARN">
<appender-ref ref="file" />
</logger>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
add to BaseTest
Logger logger = LoggerFactory.getLogger(BaseTest.class);
for example add to test:
logger.info("Test Finished");
- add dependencies to build.gradle
dependencies {
implementation 'org.testng:testng:7.4.0'
implementation 'org.seleniumhq.selenium:selenium-java:4.12.0'
implementation 'io.qameta.allure:allure-testng:2.14.0'
implementation 'io.github.bonigarcia:webdrivermanager:5.3.2'
// added new dependencies
compileOnly 'org.projectlombok:lombok:1.18.28'
annotationProcessor 'org.projectlombok:lombok:1.18.28'
testCompileOnly 'org.projectlombok:lombok:1.18.28'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.28'
- Automatic constructors getters, setters etc by lombok
package dto;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
@Builder
public class UserDTOLombok {
String name;
String lastName;
String email;
String password;
}
-
What is JavaScriptExecutor?
JavaScriptExecutor is an Interface that helps to execute JavaScript through Selenium Webdriver. JavaScriptExecutor provides two methods “executescript” & “executeAsyncScript” to run javascript on the selected window or current page.
JavaScriptExecutor in Selenium with Example -
Actions To test an application, one needs to perform a number of user actions on it. To perform any operations on the web application such as double-click, selecting drop-down boxes, etc. the actions class is required
How to handle Action class in Selenium -
BaseHelper
public void jsClickBase(String locator) {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript(locator);
}
public void clickByXY(By locator, int down, int right) { // 10 12
Rectangle rect = findElementBase(locator).getRect();
int x = rect.getX() + rect.getWidth() / 8;
int y = rect.getY() + rect.getHeight() / 2;
Actions actions = new Actions(driver);
actions.moveByOffset(x, y).click().perform();
}
- HomeWork for lesson 13:
-
- TODO in the project PhoneBook:
-
-
- Add & Run registration tests (userDTO, userDTOWith, userDTOLombok)
-
-
-
- Research and add code to connect ConfigReader.java to UserHelper.java
-
-
Lecture Recording
-
Discussions: Slack Channel Lesson 12
-
Helpers ChatGPT | Bard | stackoverflow.com
-
Check HomeWork
-
Refactoring for scale...
Create class ApplicationManager in package "manager" and offload startUp and tearDown functions
Driver per browser/database/server etc... added to @BeforeSuite
Ctrl-Alt-Shift-U - create UML diagram
- add package manager to src/test/java
-
- add class ApplicationManager.java
- add class BaseHelper.java
- add package tests to src/test/java
- add package dto to src/test/java
in ApplicationManager.java define global init and teardown functions:
public void init() {
driver = new ChromeDriver();
driver.navigate().to("https://ilcarro.web.app/search");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(60));
}
public void tearDown() {driver.quit();
}
in BaseTest.java define object from ApplicationManager class and add @BeforeSuite and @AfterSuite:
static ApplicationManager app = new ApplicationManager();
@BeforeSuite
public void setup(){
app.init();
}
@AfterSuite
public void stop(){
app.tearDown();
}
in BaseHelper redefine:
private WebElement findElementBase(By locator){
return driver.findElement(locator);
}
private List<WebElement> findElementsBase(By locator){
return driver.findElements(locator);
}
- HomeWork for lesson 12:
-
- TODO in the project PhoneBook:
-
-
- Create folder manager and there: class ApplicationManager, BaseHelper, UserHelper and fill the, like on the lesson
-
-
-
- Create folder tests and add there LoginTests and BaseTests and connect them with the applicationManager and Helpers, like on the lesson
-
-
-
- Create folder DTO and add there to types for objects – object and object with, like on the lesson, and create for both objects tests positiveLogin
-
-
-
- Run tests login (one run for test with userDto and one for test with userDTOWith)
-
- Record
- TestNG Home site
- Selenium and TestNG
- TestNG Documentation
- Additional info: Course TestNG by QA Automation и SDET
- Discussions: Slack Channel Lesson 11
-
Helpers ChatGPT | Bard | stackoverflow.com
-
Basics of TestNG
-
- Data Driven
-
- Annotations
-
- Attributes
-
Steps to create and run tests:
-
- Write the business logic of your test and insert TestNG annotations in your code.
-
- Add the information about your test (e.g. the class name, the groups you wish to run, etc...) in a testng.xml file or in build.xml.
-
- Run TestNG.
- TestNG Annotations
Аннотация — это метка, которая предоставляет дополнительную информацию о классе или методе Для аннотаций используется префикс «@». TestNG использует аннотации, чтобы помочь в создании надeжной структуры тестов.
- @BeforeSuite: аннотированный метод будет запущен до того, как будут запущены все тесты в этом наборе.
- @AfterSuite: аннотированный метод будет запущен после выполнения всех тестов в этом наборе.
- @BeforeClass : аннотированный метод будет запущен до вызова первого тестового метода в текущем классе.
- @AfterClass : аннотированный метод будет запущен после того, как будут запущены все методы тестирования в текущем классе.
- @BeforeMethod : аннотированный метод будет запускаться перед каждым тестовым методом.
- @AfterMethod : аннотированный метод будет запускаться после каждого метода тестирования.
- @BeforeTest : аннотированный метод будет запущен до запуска любого тестового метода, принадлежащего классам внутри тега .
- @AfterTest : аннотированный метод будет запущен после того, как будут запущены все методы тестирования, принадлежащие классам внутри тега .
- @BeforeGroups : список групп, которые этот метод конфигурации будет запускать раньше. Этот метод гарантированно запускается незадолго до вызова первого тестового метода, принадлежащего любой из этих групп.
- @AfterGroups: список групп, после которых будет выполняться этот метод настройки. Этот метод гарантированно запускается вскоре после вызова последнего тестового метода, принадлежащего любой из этих групп.
- TestNG Attributes
-
description: можно указать описание тестового метода.
Например, @Test(description=”этот тест проверяет вход в систему”).
-
alwaysRun: этот атрибут гарантирует, что тестовый метод будет выполнен всегда, даже в случае падения тестов, от которых он зависит. Когда значение атрибута true, этот метод будет запускаться всегда.
Например, @Test(alwaysRun= true).
-
dataProvider: задаёт имя поставщика данных (data provider) для метода. Предположим, что вы собираетесь запускать свои тесты в нескольких браузерах, тогда в тестовом методе с атрибутом dataProvider, можно добавить параметры для браузера и его версии. В этом случае тест, содержащий этот атрибут, будет использовать эти входные данные для запуска тестов в нескольких браузерах.
Например, @Test(dataProvider=”cross-browser-testing”).
-
dependsOnMethods: предоставляет информацию о порядке выполнения тестов. Тест с этим атрибутом будет выполнен, только если успешно выполниться тест, от которого он зависит. Если тест, от которого зависит метод, падает, то тест не запускается.
Например, @Test (depenOnmethod = “login”).
-
groups: помогает сгруппировать ваши тестовые методы, ориентированные на одну функциональность, в одну группу.
Например, @Test(groups={”Payment_Module”}). Этот атрибут также позволяет управлять тем, какие тесты запускать. При запуске тестов можно игнорировать какие-то группы или, наоборот, запустить только некоторые группы. Тут нужно указать нужные группы в файле TestNG.xml. В теге include указать группы, которые необходимо запустить, а в теге exclude, которые надо игнорировать.
-
priority: помогает определить приоритет тестовых методов. Когда TestNG выполняет тестовые методы, он может делать это в произвольном порядке. В сценарии, где вы хотите, чтобы ваши тесты выполнялись в нужном порядке, вы можете использовать атрибут priority. Приоритет по умолчанию для всех тестовых методов равен 0. Сначала выполняются тесты с меньшим значением priority.
Например, @Test (priority = 1), @Test (priority = 2). В этом случае сначала будет выполнен тест с приоритетом, равным единице, а потом тест с приоритетом два.TestNG атрибуты
-
enabled: этот атрибут используется, когда вам нужно игнорировать и не запускать определённый тест. Всё, что вам нужно сделать, это установить его в false.
Например, @Test(enabled= false).
-
timeout: определяет время, за которое должен выполниться тест. Если выполнение теста превышает время, определённое атрибутом, то тест завершится с ошибкой с выбросом исключения org.testng.internal.thread.ThreadTimeoutException.
Например, @Test(timeOut= 500). Обратите внимание, что время указывается в миллисекундах.
-
invocationCount: работает точно так же, как цикл. Тест будет запущен столько раз, сколько указано в invocationCount.
Например, @Test(invocationCount = 5), будет запущен 5 раз.TestNG атрибуты
-
invocationTimeOut: используется вместе с вышеуказанным атрибутом invocationCount. Значение этого атрибута вместе с invocationCount указывает на то, что тест будет запущен столько раз, сколько указано в invocationCount, и в течение времени, указанного в атрибуте invocationTimeOut.
Например, @Test(invocationCount = 5, invocationTimeOut = 20).
-
expectedExceptions: помогает обрабатывать исключения, выброс которых ожидается в тестовом методе. Если исключение, указанное в атрибуте, выброшено тестовым методом, то тест прошёл успешно. В противном случае, отсутствие исключения или выброс другого исключения, не указанного в атрибуте, провалит тест.
Например:
@Test(expectedExceptions = {ArithmeticException.class }).
-
DataProviders
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@DataProvider(name = "testData")
public Object[][] testData() {
return new Object[][] {
{"username1", "password1"},
{"username2", "password2"},
{"username3", "password3"}
};
}
@Test(dataProvider = "testData")
public void loginTest(String username, String password) {
System.out.println("Logging in with username: " + username + ", password: " + password);
// Your test logic goes here
}
- Some commonly used assertion methods in TestNG
-
- Assert.assertTrue
int result = 2 + 2;
Assert.assertTrue(result == 4, "Expected result to be 4, but found " + result);
-
- assertFalse
int result = 2 + 2;
Assert.assertFalse(condition, message);
-
- assertEquals
int result = 2 + 2;
Assert.assertEquals(result, 4, "Expected result to be 4, but found " + result);
Запись в build.gradle для запуска из разных Xml
task reg(type: Test){
useTestNG {
def suite = System.getProperty('suite', '')
if (suite.equals('quick')) {
suites 'src/test/resources/quick.xml'
} else if (suite.equals('smoke')) {
suites 'src/test/resources/smoke.xml'
} else {
suites 'src/test/resources/testng.xml'
}
if (project.hasProperty('browser')) {
systemProperty 'browser', "${browser}"
}
}
}
- Parallel tests
@Test(threadPoolSize = 3, invocationCount = 10, timeOut = 10000)
-
Графический результат можно найти в папке
build->reports->tests->reg->index.html -
Example
BinarySearch Algorithm
public class BinarySearch {
public int binarySearch(int[] arr, int x)
{
int l = 0, r = arr.length - 1;
while (l <= r) {
int m = l + (r - l) / 2;
// Check if x is present at mid
if (arr[m] == x)
return m;
// If x greater, ignore left half
if (arr[m] < x)
l = m + 1;
// If x is smaller, ignore right half
else
r = m - 1;
}
// If we reach here, then element was
// not present
return -1;
}
Test:
@Test(groups = {"perftest", "checkintest"}, dataProvider = "testDataTime", priority = 1, threadPoolSize = 3, invocationCount = 10, timeOut = 10000)
public void testArr1000Perf(int arr_size, int x, int expected_time, Method method) {
BinarySearch bs = new BinarySearch();
int[] arr = new int[arr_size + 1];
for (int z = 0; z <= arr_size; z++) {
arr[z] = z;
}
long start = System.nanoTime();
bs.binarySearch(arr, 5);
long end = System.nanoTime();
long diff = end - start;
System.out.println(start + " " + end + " " + diff);
Assert.assertTrue(diff < expected_time, "diff lower than expected");
}
}
@Test(groups = {"functest", "second-group"},dataProvider = "testData", description = "Functionality test")
public void testArr1000Func(int arr_size, int x, int expected_element) {
int[] arr = new int[arr_size + 1];
for (int z = 0; z <= arr_size; z++) {
arr[z] = z;
}
BinarySearch ob = new BinarySearch();
int result = ob.binarySearch(arr, x);
Assert.assertEquals(result, expected_element);
}
- HomeWork:
-
- Refactor code SeleniumXpathIcarro.java and SeleniumCssIcarro.java using @Test and Asserts
-
- Write code SeleniumXpathPhoneBook.java
-
- Fix errors in LoginTests.java
- commit and Pull Request for review (All questions and discussions here, try team work for solving issues: Slack Channel Lesson 11)