Skip to content

Commit 810868e

Browse files
committed
Bài 28 - Build Framework cá nhân hoàn chỉnh
1 parent 2c777d2 commit 810868e

File tree

11 files changed

+417
-350
lines changed

11 files changed

+417
-350
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<dependency>
2828
<groupId>org.testng</groupId>
2929
<artifactId>testng</artifactId>
30-
<version>7.4.0</version>
30+
<version>7.11.0</version>
3131
</dependency>
3232

3333
<!-- https://mvnrepository.com/artifact/io.appium/java-client -->

src/main/java/com/anhtester/constants/ConfigData.java

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,48 +10,54 @@
1010

1111
public class ConfigData {
1212

13-
private ConfigData() {
14-
// Ngăn chặn khởi tạo class
15-
}
16-
17-
// Load all properties files
18-
static {
19-
PropertiesHelpers.loadAllFiles();
20-
}
21-
22-
public static final String PROJECT_PATH = SystemHelpers.getCurrentDir();
23-
public static final String EXCEL_DATA_FILE_PATH = PropertiesHelpers.getValue("EXCEL_DATA_FILE_PATH");
24-
public static final String JSON_DATA_FILE_PATH = PropertiesHelpers.getValue("JSON_DATA_FILE_PATH");
25-
public static final String JSON_CONFIG_FILE_PATH = PropertiesHelpers.getValue("JSON_CONFIG_FILE_PATH");
26-
public static final String TEST_DATA_FOLDER_PATH = PropertiesHelpers.getValue("TEST_DATA_FOLDER_PATH");
27-
public static final String LOCATE = PropertiesHelpers.getValue("LOCATE");
28-
public static final String TIMEOUT_SERVICE = PropertiesHelpers.getValue("TIMEOUT_SERVICE");
29-
public static final String TIMEOUT_EXPLICIT_DEFAULT = PropertiesHelpers.getValue("TIMEOUT_EXPLICIT_DEFAULT");
30-
public static final String APPIUM_DRIVER_LOCAL_SERVICE = PropertiesHelpers.getValue("APPIUM_DRIVER_LOCAL_SERVICE");
31-
32-
public static final String STEP_ACTION_TIMEOUT = PropertiesHelpers.getValue("STEP_ACTION_TIMEOUT");
33-
34-
public static String getValueJsonConfig(String platform, String device, String propertyName) {
35-
// Initialize Jackson ObjectMapper
36-
ObjectMapper mapper = new ObjectMapper();
37-
// Read JSON file
38-
JsonNode rootNode = null;
39-
try {
40-
rootNode = mapper.readTree(new File(ConfigData.JSON_CONFIG_FILE_PATH));
41-
} catch (IOException e) {
42-
throw new RuntimeException(e);
43-
}
44-
45-
String result = rootNode
46-
.path("platforms")
47-
.path(platform.trim().toLowerCase())
48-
.path("devices")
49-
.path(device.trim().toLowerCase())
50-
.path(propertyName)
51-
.asText();
52-
53-
System.out.println("***" + propertyName + ": " + result);
54-
return result;
55-
}
13+
private ConfigData() {
14+
// Ngăn chặn khởi tạo class
15+
}
16+
17+
// Load all properties files
18+
static {
19+
PropertiesHelpers.loadAllFiles();
20+
}
21+
22+
public static final String PROJECT_PATH = SystemHelpers.getCurrentDir();
23+
public static final String EXCEL_DATA_FILE_PATH = PropertiesHelpers.getValue("EXCEL_DATA_FILE_PATH");
24+
public static final String JSON_DATA_FILE_PATH = PropertiesHelpers.getValue("JSON_DATA_FILE_PATH");
25+
public static final String JSON_CONFIG_FILE_PATH = PropertiesHelpers.getValue("JSON_CONFIG_FILE_PATH");
26+
public static final String TEST_DATA_FOLDER_PATH = PropertiesHelpers.getValue("TEST_DATA_FOLDER_PATH");
27+
public static final String LOCATE = PropertiesHelpers.getValue("LOCATE");
28+
public static final String TIMEOUT_SERVICE = PropertiesHelpers.getValue("TIMEOUT_SERVICE");
29+
public static final String TIMEOUT_EXPLICIT_DEFAULT = PropertiesHelpers.getValue("TIMEOUT_EXPLICIT_DEFAULT");
30+
public static final String APPIUM_DRIVER_LOCAL_SERVICE = PropertiesHelpers.getValue("APPIUM_DRIVER_LOCAL_SERVICE");
31+
public static final String STEP_ACTION_TIMEOUT = PropertiesHelpers.getValue("STEP_ACTION_TIMEOUT");
32+
public static final String SCREENSHOT_FAIL = PropertiesHelpers.getValue("SCREENSHOT_FAIL");
33+
public static final String SCREENSHOT_PASS = PropertiesHelpers.getValue("SCREENSHOT_PASS");
34+
public static final String SCREENSHOT_ALL_STEP = PropertiesHelpers.getValue("SCREENSHOT_ALL_STEP");
35+
public static final String SCREENSHOT_PATH = PropertiesHelpers.getValue("SCREENSHOT_PATH");
36+
public static final String RECORD_VIDEO = PropertiesHelpers.getValue("RECORD_VIDEO");
37+
public static final String RECORD_VIDEO_PATH = PropertiesHelpers.getValue("RECORD_VIDEO_PATH");
38+
39+
40+
public static String getValueJsonConfig(String platform, String device, String propertyName) {
41+
// Initialize Jackson ObjectMapper
42+
ObjectMapper mapper = new ObjectMapper();
43+
// Read JSON file
44+
JsonNode rootNode = null;
45+
try {
46+
rootNode = mapper.readTree(new File(ConfigData.JSON_CONFIG_FILE_PATH));
47+
} catch (IOException e) {
48+
throw new RuntimeException(e);
49+
}
50+
51+
String result = rootNode
52+
.path("platforms")
53+
.path(platform.trim().toLowerCase())
54+
.path("devices")
55+
.path(device.trim().toLowerCase())
56+
.path(propertyName)
57+
.asText();
58+
59+
System.out.println("***" + propertyName + ": " + result);
60+
return result;
61+
}
5662

5763
}
Lines changed: 57 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.anhtester.helpers;
22

3+
import com.anhtester.constants.ConfigData;
34
import com.anhtester.drivers.DriverManager;
45
import com.anhtester.utils.DateUtils;
56
import io.appium.java_client.android.AndroidDriver;
@@ -18,66 +19,66 @@
1819
import java.util.Base64;
1920

2021
public class CaptureHelpers {
21-
/**
22-
* Hàm static để chụp ảnh màn hình và lưu vào đường dẫn file được chỉ định.
23-
*
24-
* @param fileName Đường dẫn file nơi muốn lưu ảnh chụp màn hình (ví dụ: "screenshots/image.png").
25-
*/
26-
public static void captureScreenshot(String fileName) {
27-
try {
28-
// Ép kiểu driver thành TakesScreenshot để lấy ảnh màn hình
29-
File srcFile = ((TakesScreenshot) DriverManager.getDriver()).getScreenshotAs(OutputType.FILE);
22+
/**
23+
* Hàm static để chụp ảnh màn hình và lưu vào đường dẫn file được chỉ định.
24+
*
25+
* @param fileName Đường dẫn file nơi muốn lưu ảnh chụp màn hình (ví dụ: "screenshots/image.png").
26+
*/
27+
public static void captureScreenshot(String fileName) {
28+
try {
29+
// Ép kiểu driver thành TakesScreenshot để lấy ảnh màn hình
30+
File srcFile = ((TakesScreenshot) DriverManager.getDriver()).getScreenshotAs(OutputType.FILE);
3031

31-
SystemHelpers.createFolder(SystemHelpers.getCurrentDir() + "exports/screenshots");
32-
String filePath = SystemHelpers.getCurrentDir() + "exports/screenshots/" + fileName + "_" + Thread.currentThread().getId() + "_" + SystemHelpers.makeSlug(DateUtils.getCurrentDateTime()) + ".png";
32+
SystemHelpers.createFolder(SystemHelpers.getCurrentDir() + ConfigData.SCREENSHOT_PATH);
33+
String filePath = SystemHelpers.getCurrentDir() + ConfigData.SCREENSHOT_PATH + fileName + "_" + Thread.currentThread().getId() + "_" + SystemHelpers.makeSlug(DateUtils.getCurrentDateTime()) + ".png";
3334

34-
// Tạo đối tượng Path cho file đích
35-
Path targetPath = new File(filePath).toPath();
35+
// Tạo đối tượng Path cho file đích
36+
Path targetPath = new File(filePath).toPath();
3637

37-
// Sao chép file từ nguồn sang đích, thay thế file nếu đã tồn tại
38-
Files.copy(srcFile.toPath(), targetPath, StandardCopyOption.REPLACE_EXISTING);
39-
System.out.println("Chụp ảnh màn hình thành công, lưu tại: " + targetPath.toAbsolutePath());
40-
} catch (IOException e) {
41-
System.err.println("Lỗi trong quá trình lưu file ảnh: " + e.getMessage());
42-
e.printStackTrace();
43-
} catch (Exception e) {
44-
System.err.println("Lỗi trong quá trình chụp ảnh màn hình: " + e.getMessage());
45-
e.printStackTrace();
46-
}
47-
}
38+
// Sao chép file từ nguồn sang đích, thay thế file nếu đã tồn tại
39+
Files.copy(srcFile.toPath(), targetPath, StandardCopyOption.REPLACE_EXISTING);
40+
System.out.println("Chụp ảnh màn hình thành công, lưu tại: " + targetPath.toAbsolutePath());
41+
} catch (IOException e) {
42+
System.err.println("Lỗi trong quá trình lưu file ảnh: " + e.getMessage());
43+
e.printStackTrace();
44+
} catch (Exception e) {
45+
System.err.println("Lỗi trong quá trình chụp ảnh màn hình: " + e.getMessage());
46+
e.printStackTrace();
47+
}
48+
}
4849

49-
// Bắt đầu ghi video
50-
public static void startRecording() {
51-
if (DriverManager.getDriver() != null) {
52-
((AndroidDriver) DriverManager.getDriver()).startRecordingScreen(
53-
new AndroidStartScreenRecordingOptions()
54-
.withBitRate(4000000) // default: 4000000
55-
.withVideoSize("1080x2400") // 720 x 1600, 1080 x 2400 pixels
56-
.withTimeLimit(Duration.ofMinutes(10))); // 10 minutes max video length
57-
System.out.println("Bắt đầu ghi video cho " + DriverManager.getDriver().getCapabilities().getCapability("deviceName"));
58-
}
59-
}
50+
// Bắt đầu ghi video
51+
public static void startRecording() {
52+
if (DriverManager.getDriver() != null) {
53+
((AndroidDriver) DriverManager.getDriver()).startRecordingScreen(
54+
new AndroidStartScreenRecordingOptions()
55+
.withBitRate(4000000) // default: 4000000
56+
.withVideoSize("1080x2400") // 720 x 1600, 1080 x 2400 pixels
57+
.withTimeLimit(Duration.ofMinutes(10))); // 10 minutes max video length
58+
System.out.println("Bắt đầu ghi video cho " + DriverManager.getDriver().getCapabilities().getCapability("deviceName"));
59+
}
60+
}
6061

61-
// Dừng ghi video và lưu file
62-
public static void stopRecording(String videoFileName) {
63-
if (DriverManager.getDriver() != null) {
64-
try {
65-
String base64Video = ((CanRecordScreen) ((AndroidDriver) DriverManager.getDriver())).stopRecordingScreen();
66-
System.out.println("Base64 video length: " + (base64Video != null ? base64Video.length() : "null"));
67-
if (base64Video != null && !base64Video.isEmpty()) {
68-
byte[] videoBytes = Base64.getDecoder().decode(base64Video);
69-
System.out.println("Video bytes length: " + videoBytes.length);
70-
File videoFile = new File(videoFileName);
71-
try (FileOutputStream fos = new FileOutputStream(videoFile)) {
72-
fos.write(videoBytes);
73-
}
74-
System.out.println("Video được lưu tại: " + videoFile.getAbsolutePath() + " (Size: " + videoFile.length() + " bytes)");
75-
} else {
76-
System.out.println("Không có dữ liệu video để lưu.");
77-
}
78-
} catch (Exception e) {
79-
System.err.println("Lỗi khi dừng ghi video: " + e.getMessage());
62+
// Dừng ghi video và lưu file
63+
public static void stopRecording(String videoFileName) {
64+
if (DriverManager.getDriver() != null) {
65+
try {
66+
String base64Video = ((CanRecordScreen) ((AndroidDriver) DriverManager.getDriver())).stopRecordingScreen();
67+
System.out.println("Base64 video length: " + (base64Video != null ? base64Video.length() : "null"));
68+
if (base64Video != null && !base64Video.isEmpty()) {
69+
byte[] videoBytes = Base64.getDecoder().decode(base64Video);
70+
System.out.println("Video bytes length: " + videoBytes.length);
71+
File videoFile = new File(videoFileName);
72+
try (FileOutputStream fos = new FileOutputStream(videoFile)) {
73+
fos.write(videoBytes);
74+
}
75+
System.out.println("Video được lưu tại: " + videoFile.getAbsolutePath() + " (Size: " + videoFile.length() + " bytes)");
76+
} else {
77+
System.out.println("Không có dữ liệu video để lưu.");
8078
}
81-
}
82-
}
79+
} catch (Exception e) {
80+
System.err.println("Lỗi khi dừng ghi video: " + e.getMessage());
81+
}
82+
}
83+
}
8384
}

src/main/java/com/anhtester/keywords/MobileUI.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,34 +191,49 @@ public static void scrollGestureCommand() {
191191
public static void clickElement(By locator, int second) {
192192
sleep(STEP_ACTION_TIMEOUT);
193193
LogUtils.info("[MobileUI] Clicking element located by: " + locator + " within " + second + "s.");
194+
if (ConfigData.SCREENSHOT_ALL_STEP.equalsIgnoreCase("true")) {
195+
AllureManager.saveScreenshotPNG();
196+
}
194197
waitForElementToBeClickable(locator, second).click();
195198
}
196199

197200
@Step("Click element {0}")
198201
public static void clickElement(By locator) {
199202
sleep(STEP_ACTION_TIMEOUT);
200203
LogUtils.info("[MobileUI] Clicking element located by: " + locator + " within default timeout (" + DEFAULT_TIMEOUT + "s).");
204+
if (ConfigData.SCREENSHOT_ALL_STEP.equalsIgnoreCase("true")) {
205+
AllureManager.saveScreenshotPNG();
206+
}
201207
waitForElementToBeClickable(locator).click();
202208
}
203209

204210
@Step("Click element {0} within {1}s")
205211
public static void clickElement(WebElement element, int second) {
206212
sleep(STEP_ACTION_TIMEOUT);
207213
LogUtils.info("[MobileUI] Clicking element: " + element + " within " + second + "s.");
214+
if (ConfigData.SCREENSHOT_ALL_STEP.equalsIgnoreCase("true")) {
215+
AllureManager.saveScreenshotPNG();
216+
}
208217
waitForElementToBeClickable(element, second).click();
209218
}
210219

211220
@Step("Click element {0}")
212221
public static void clickElement(WebElement element) {
213222
sleep(STEP_ACTION_TIMEOUT);
214223
LogUtils.info("[MobileUI] Clicking element: " + element + " within default timeout (" + DEFAULT_TIMEOUT + "s).");
224+
if (ConfigData.SCREENSHOT_ALL_STEP.equalsIgnoreCase("true")) {
225+
AllureManager.saveScreenshotPNG();
226+
}
215227
waitForElementToBeClickable(element).click();
216228
}
217229

218230
@Step("Set text '{1}' on element {0}")
219231
public static void setText(By locator, String text) {
220232
sleep(STEP_ACTION_TIMEOUT);
221233
LogUtils.info("[MobileUI] Setting text '" + text + "' on element located by: " + locator + " with default timeout.");
234+
if (ConfigData.SCREENSHOT_ALL_STEP.equalsIgnoreCase("true")) {
235+
AllureManager.saveScreenshotPNG();
236+
}
222237
WebElement element = waitForElementVisible(locator);
223238
element.click(); // Often needed before clear/sendKeys
224239
element.clear();
@@ -230,6 +245,9 @@ public static void setText(By locator, String text) {
230245
public static void setText(By locator, String text, int second) {
231246
sleep(STEP_ACTION_TIMEOUT);
232247
LogUtils.info("[MobileUI] Setting text '" + text + "' on element located by: " + locator + " with timeout " + second + "s.");
248+
if (ConfigData.SCREENSHOT_ALL_STEP.equalsIgnoreCase("true")) {
249+
AllureManager.saveScreenshotPNG();
250+
}
233251
WebElement element = waitForElementVisible(locator, second);
234252
element.click();
235253
element.clear();
@@ -241,6 +259,9 @@ public static void setText(By locator, String text, int second) {
241259
public static void setText(WebElement element, String text) {
242260
sleep(STEP_ACTION_TIMEOUT);
243261
LogUtils.info("[MobileUI] Setting text '" + text + "' on element: " + element + " with default timeout.");
262+
if (ConfigData.SCREENSHOT_ALL_STEP.equalsIgnoreCase("true")) {
263+
AllureManager.saveScreenshotPNG();
264+
}
244265
WebElement elm = waitForElementVisible(element);
245266
elm.click();
246267
elm.clear();
@@ -253,6 +274,9 @@ public static void setText(WebElement element, String text) {
253274
public static void setText(WebElement element, String text, int second) {
254275
sleep(STEP_ACTION_TIMEOUT);
255276
LogUtils.info("[MobileUI] Setting text '" + text + "' on element: " + element + " with timeout " + second + "s.");
277+
if (ConfigData.SCREENSHOT_ALL_STEP.equalsIgnoreCase("true")) {
278+
AllureManager.saveScreenshotPNG();
279+
}
256280
WebElement elm = waitForElementVisible(element, second);
257281
elm.click();
258282
elm.clear();

src/main/java/com/anhtester/reports/AllureManager.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,20 @@
66
import org.openqa.selenium.TakesScreenshot;
77

88
public class AllureManager {
9-
//Text attachments for Allure
10-
@Attachment(value = "{0}", type = "text/plain")
11-
public static String saveTextLog(String message) {
12-
return message;
13-
}
9+
//Text attachments for Allure
10+
@Attachment(value = "{0}", type = "text/plain")
11+
public static String saveTextLog(String message) {
12+
return message;
13+
}
1414

15-
//Screenshot attachments for Allure
16-
@Attachment(value = "Page screenshot", type = "image/png")
17-
public static byte[] saveScreenshotPNG() {
18-
return ((TakesScreenshot) DriverManager.getDriver()).getScreenshotAs(OutputType.BYTES);
19-
}
15+
//Screenshot attachments for Allure
16+
@Attachment(value = "Page_Screenshot", type = "image/png")
17+
public static byte[] saveScreenshotPNG() {
18+
return ((TakesScreenshot) DriverManager.getDriver()).getScreenshotAs(OutputType.BYTES);
19+
}
20+
21+
@Attachment(value = "{0}", type = "image/png")
22+
public static byte[] saveScreenshotPNG(String screenshotName) {
23+
return ((TakesScreenshot) DriverManager.getDriver()).getScreenshotAs(OutputType.BYTES);
24+
}
2025
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.anhtester.Bai28_BuildFramework;
2+
3+
public class Demo {
4+
}

0 commit comments

Comments
 (0)