NỘI DUNG BÀI HỌC

Chụp screenshot màn hình và record video sau khi run Test Case

1. Take Screenshot khi chạy test case

Chụp ảnh màn hình lại để khi mình chạy Pass hay Fail sẽ có cái nhìn trực quan lưu lại được từng case xử lý và cả record video nữa.

Đầu tiên nghiên cứu đoạn code Take Screenshot trước nè:

// Tạo tham chiếu của TakesScreenshot
TakesScreenshot ts = (TakesScreenshot) driver;
// Gọi hàm capture screenshot - getScreenshotAs
File source = ts.getScreenshotAs(OutputType.FILE);
// result.getName() lấy tên của test case xong gán cho tên File chụp màn hình luôn
FileHandler.copy(source, new File("./Screenshots/" + result.getName() + ".png"));
System.out.println("Screenshot taken: " + result.getName());

Hàm FileHandler.copy để sao chép source dạng file ở trên vào đường dẫn khai báo trong hàm File() với đuôi dạng hình ảnh như: png, jpg, jpeg.

Còn cái result từ đâu ra. Nó là lớp ITestResult là một giao diện Interface của TestNG hỗ trợ.

Gọi nó lại bằng cách bỏ vào trực tiếp tham số trong hàm với đối tượng như khai báo class

@Test
public void homePage(ITestResult result) throws Exception {
    driver.get("https://anhtester.com");
    //step này fail sẽ chụp màn hình lại
    assertEquals(driver.getTitle(), "Anh Tester - Automation Test");

   //Code chụp màn hình bên trên vào đây

}

Với đối tượng result thuộc giao diện ITestResult thì chúng ta có các hàm hỗ trợ sau:

[Selenium Java] Bài 25: Chụp screenshot và record video sau khi run Test Case | Anh Tester

Hiện tại chúng ta lấy cái Name của Test case dùng hàm getName() hiện tại thôi để đặt tên cho ảnh chụp dễ hình dung là ở page trang và step gì.

Lúc này code đầy đủ như này:

@Test
	public void homePage(ITestResult result) throws Exception {
		driver.get("https://anhtester.com");
		assertEquals(driver.getTitle(), "Anh Tester - Automation Test");

		// Chụp màn hình step này lại
		// Tạo tham chiếu của TakesScreenshot
		TakesScreenshot ts = (TakesScreenshot) driver;
		// Gọi hàm capture screenshot - getScreenshotAs
		File source = ts.getScreenshotAs(OutputType.FILE);
		// result.getName() lấy tên của test case xong gán cho tên File chụp màn hình
		FileHandler.copy(source, new File("./Screenshots/" + result.getName() + ".png"));
		System.out.println("Đã chụp màn hình: " + result.getName());
	}

Nó lưu file có tên là "homePage" tên test step và lưu vào thư mục "Screenshots"

[Selenium Java] Bài 25: Chụp screenshot và record video sau khi run Test Case | Anh TesterThư mục tạo sẵn cũng được hoặc nếu không tạo trước thì nó chạy xong tự tạo sinh ra luôn.

Vậy là xong rồi. Thử đi nào.

Rồi bây giờ làm cách nào để chỉ chụp những màn hình với step bị Faill hoặc đã Pass


Cách chụp ảnh màn hình cho những trường hợp Fail

Chúng ta nhớ lại cái @AfterMethod chứ hả. Nó sẽ chạy sau mỗi @Test. Và nó đó, chính là nó chứ không ai =))

Mình kết hợp nó với ITestResult trên đã nói để thiết lặp trường hợp là sau mỗi lần chạy xong @Test thì check trạng thái để chụp hình theo trạng thái đặt điều kiện tùy ý.

Dô code luôn nè

// Nó sẽ thực thi sau mỗi lần thực thi testcase (@Test)
	@AfterMethod
	public void takeScreenshot(ITestResult result) {
		// Khởi tạo đối tượng result thuộc ITestResult để lấy trạng thái và tên của từng Step
		// Ở đây sẽ so sánh điều kiện nếu testcase passed hoặc failed
		// passed = SUCCESS và failed = FAILURE
		if (ITestResult.FAILURE == result.getStatus()) {
			try {
				// Tạo tham chiếu của TakesScreenshot
				TakesScreenshot ts = (TakesScreenshot) driver;
				// Gọi hàm capture screenshot - getScreenshotAs
				File source = ts.getScreenshotAs(OutputType.FILE);
				// result.getName() lấy tên của test case xong gán cho tên File chụp màn hình
				FileHandler.copy(source, new File("./Screenshots/" + result.getName() + ".png"));
				System.out.println("Screenshot taken: " + result.getName());
			} catch (Exception e) {
				System.out.println("Exception while taking screenshot " + e.getMessage());
			}
		}
	}

Cái thằng ITestResult.FAILURE là lấy trạng thái gốc của giao diện hỗ trợ so sánh với trạng thái của Test case trả về từ Result

Rồi thôi vậy là xong.


Code mẫu để chụp ảnh màn hình cho 2 cái @Test

public class CaptureScreenshot {

	private WebDriver driver;
	
	@BeforeClass
	public void setup() {
		WebDriverManager.chromedriver().setup();
		driver = new ChromeDriver();
		
		driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
		driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
		driver.manage().window().maximize();
	}
	
	@Test
	public void homePage() throws Exception {
		driver.get("https://anhtester.com");
		//step này cố tình Fail để chụp màn hình lại
		assertEquals(driver.getTitle(), "Anh Tester - Automation Test");
	}
	
	@Test
	public void loginPage() throws Exception {
		driver.findElement(By.id("btn-login")).click();
	}

	// Nó sẽ thực thi sau mỗi lần thực thi testcase (@Test)
	@AfterMethod
	public void takeScreenshot(ITestResult result) {
		//Khởi tạo đối tượng result thuộc ITestResult để lấy trạng thái và tên của từng Test Case
		//Ở đây sẽ so sánh điều kiện nếu testcase passed hoặc failed
		//passed = SUCCESS và failed = FAILURE
		if (ITestResult.FAILURE == result.getStatus()) {
			try {
				// Tạo tham chiếu của TakesScreenshot
				TakesScreenshot ts = (TakesScreenshot) driver;
				// Gọi hàm capture screenshot - getScreenshotAs
				File source = ts.getScreenshotAs(OutputType.FILE);
				// result.getName() lấy tên của test case xong gán cho tên File chụp màn hình luôn
				FileHandler.copy(source, new File("./Screenshots/" + result.getName() + ".png"));
				System.out.println("Screenshot taken: " + result.getName());
			} catch (Exception e) {
				System.out.println("Exception while taking screenshot " + e.getMessage());
			}
		}
	}
	
	@AfterClass
	public void tearDown() throws Exception
	{
		Thread.sleep(2000);
		driver.quit();
	}

}

Lúc này cái @Test của homePage sẽ Fail nên nó chỉ ra ảnh của homePage. Chứ nó mà sinh ra thêm tấm của loginPage thì thấy bà luôn =))

[Selenium Java] Bài 25: Chụp screenshot và record video sau khi run Test Case | Anh Tester

[Selenium Java] Bài 25: Chụp screenshot và record video sau khi run Test Case | Anh Tester

Rồi xong rồi đó

2. Record video khi chạy test case

Vụ record này hay nè. Hay hơn cả screenshot vì thằng này giúp mình khi chạy xong đống Test case của project là mang video để đi demo nộp bàn giao luôn =))

Thằng Record này dùng nó phải có thư viện hỗ trợ riêng chứ trong TestNG không có hỗ trợ hàm sẵn

An chỉ các bạn có 2 thư viện là Monte MediaATU Test Recorder

2.1 Record Screen với thư viện Monte Media

Tải gói thư viện về trước: MonteScreenRecorder.jar

[Selenium Java] Bài 25: Chụp screenshot và record video sau khi run Test Case | Anh Tester

Import nó vào Build Path của project mình

[Selenium Java] Bài 25: Chụp screenshot và record video sau khi run Test Case | Anh Tester

Để sử dụng nó thì chúng ta tạo ra 1 class riêng để xây dựng nó ví dụ tên RecordVideo và sau đó chèn các thư viện sau:

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.monte.media.Format;
import org.monte.media.FormatKeys.MediaType;
import org.monte.media.Registry;
import org.monte.media.math.Rational;
import org.monte.screenrecorder.ScreenRecorder;
import static org.monte.media.AudioFormatKeys.*;
import static org.monte.media.VideoFormatKeys.*;

Cái class đó các các bạn phải kế thừa bằng cách extends cái class xây dựng sẵn trong thư viện Monte là ScreenRecorder

 

Tiếp đến là xây dựng 2 hàm startRecordstopRecord như sau:

package AnhTester.Record;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.monte.media.Format;
import org.monte.media.FormatKeys.MediaType;
import org.monte.media.Registry;
import org.monte.media.math.Rational;
import org.monte.screenrecorder.ScreenRecorder;
import static org.monte.media.AudioFormatKeys.*;
import static org.monte.media.VideoFormatKeys.*;

public class RecordVideo extends ScreenRecorder {

// ------Record with Monte Media library---------
	public static ScreenRecorder screenRecorder;
	public String name;
	
	//Hàm xây dựng
	public RecordVideo(GraphicsConfiguration cfg, Rectangle captureArea, Format fileFormat, Format screenFormat,
			Format mouseFormat, Format audioFormat, File movieFolder, String name) throws IOException, AWTException {
		super(cfg, captureArea, fileFormat, screenFormat, mouseFormat, audioFormat, movieFolder);
		this.name = name;
	}

	//Hàm này bắt buộc để ghi đè custom lại hàm trong thư viên viết sẵn
	@Override
	protected File createMovieFile(Format fileFormat) throws IOException {

		if (!movieFolder.exists()) {
			movieFolder.mkdirs();
		} else if (!movieFolder.isDirectory()) {
			throw new IOException("\"" + movieFolder + "\" is not a directory.");
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH-mm-ss");
		return new File(movieFolder,
				name + "-" + dateFormat.format(new Date()) + "." + Registry.getInstance().getExtension(fileFormat));
	}

	// Hàm Start record video
	public static void startRecord(String methodName) throws Exception {
		//Tạo thư mục để lưu file video vào
		File file = new File("./test-recordings/");
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		int width = screenSize.width;
		int height = screenSize.height;

		Rectangle captureSize = new Rectangle(0, 0, width, height);

		GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
				.getDefaultConfiguration();
		screenRecorder = new RecordVideo(gc, captureSize,
				new Format(MediaTypeKey, MediaType.FILE, MimeTypeKey, MIME_AVI),
				new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
						CompressorNameKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, DepthKey, 24, FrameRateKey,
						Rational.valueOf(15), QualityKey, 1.0f, KeyFrameIntervalKey, 15 * 60),
				new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, "black", FrameRateKey, Rational.valueOf(30)),
				null, file, methodName);
		screenRecorder.start();
	}

	// Stop record video
	public static void stopRecord() throws Exception {
		screenRecorder.stop();
	}
}


Vậy là đã xong 2 hàm rồi

Bây giờ gọi lại 2 hàm đó thì để cái hàm startRecord vào chổ @BeforeClassstopRecord vào chổ @AfterClass ở từng class test case là xong. Như này nè

package AnhTester.Record;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import io.github.bonigarcia.wdm.WebDriverManager;

public class RecordVideoCallFunction {

	private WebDriver driver;

	@BeforeClass
	public void setupClass() throws Exception {
		WebDriverManager.chromedriver().setup();
		driver = new ChromeDriver();
		driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
		driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
		driver.manage().window().maximize();
		
		// Gọi lại hàm startRecord
		RecordVideo.startRecord("ManageDocument");
	}

	@Test
	public void homePage() throws Exception {
		driver.get("https://anhtester.com");
		Thread.sleep(2000);
		driver.findElement(By.id("btn-login")).click();
	}
	
	@AfterTest
	public void tearDownTestCase() throws Exception {
		Thread.sleep(2000);
		driver.quit();
	}

	@AfterClass
	public void tearDownClass() throws Exception {
		// Gọi lại hàm startRecord
		RecordVideo.stopRecord();
	}
}

Chạy xong nó xuất ra video như này đây

[Selenium Java] Bài 25: Chụp screenshot và record video sau khi run Test Case | Anh Tester

Thằng Monte này xuất file đuôi là AVI khá sắc nét.

2.2 Record Screen với thư viện ATU Test Recorder

Tải cái gói thư viện jar về:  ATUTestRecorder.jar

[Selenium Java] Bài 25: Chụp screenshot và record video sau khi run Test Case | Anh Tester


Bắt đầu dùng thì cũng phải là chèn gói đó vào Build Path của project thôi =))

[Selenium Java] Bài 25: Chụp screenshot và record video sau khi run Test Case | Anh Tester

Cũng tương tự Monte trên thì chúng ta tạo class và chèn thư viện vào

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import atu.testrecorder.ATUTestRecorder;


Dô code luôn nào cho nhanh gọn lẹ

package AnhTester.Record;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import atu.testrecorder.ATUTestRecorder;

public class RecordVideo {

	// ------Record with ATU library-----------
	public static ATUTestRecorder recorder;
	static DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH-mm-ss");
	static Date date = new Date();

	public static void startRecordATU(String videoName) throws Exception {
		recorder = new ATUTestRecorder("./test-recordings/", videoName + "-" + dateFormat.format(date), false);
		recorder.start();
	}

	public static void stopRecordATU() throws Exception {
		recorder.stop();
	}
}


Nó đơn giản hơn thằng Monte nữa đúng không. Khác là thằng này xuất file đuôi là MOV nhẹ hơn AVI

Và chúng ta gọi 2 hàm startRecordATUstopRecordATU giống như Monte bên trên là bỏ vào tuần tự @BeforeClass@AfterClass

package AnhTester.Record;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import io.github.bonigarcia.wdm.WebDriverManager;

public class RecordVideoCallFunction {

	private WebDriver driver;

	@BeforeClass
	public void setupClass() throws Exception {
		WebDriverManager.chromedriver().setup();
		driver = new ChromeDriver();
		driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
		driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
		driver.manage().window().maximize();
		
		// Gọi lại hàm startRecordATU
		RecordVideo.startRecordATU("ManageDocument");
	}

	@Test
	public void homePage() throws Exception {
		driver.get("https://anhtester.com");
		Thread.sleep(2000);
		driver.findElement(By.id("btn-login")).click();
	}
	
	@AfterTest
	public void tearDownTestCase() throws Exception {
		Thread.sleep(2000);
		driver.quit();
	}

	@AfterClass
	public void tearDownClass() throws Exception {
		// Gọi lại hàm startRecordATU
		RecordVideo.stopRecordATU();
	}
}


Xuất file video đuôi MOV

[Selenium Java] Bài 25: Chụp screenshot và record video sau khi run Test Case | Anh Tester

Và các bạn khi đã nắm từng class rõ rồi của 2 thư viện thì giờ gộp lại chung 1 class luôn cho dễ gọi

package AnhTester.Record;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.monte.media.Format;
import org.monte.media.FormatKeys.MediaType;
import org.monte.media.Registry;
import org.monte.media.math.Rational;
import org.monte.screenrecorder.ScreenRecorder;
import static org.monte.media.AudioFormatKeys.*;
import static org.monte.media.VideoFormatKeys.*;

import atu.testrecorder.ATUTestRecorder;

public class RecordVideo extends ScreenRecorder {

	// ------Record with Monte Media library---------
	public static ScreenRecorder screenRecorder;
	public String name;
	
	//Hàm xây dựng
	public RecordVideo(GraphicsConfiguration cfg, Rectangle captureArea, Format fileFormat, Format screenFormat,
			Format mouseFormat, Format audioFormat, File movieFolder, String name) throws IOException, AWTException {
		super(cfg, captureArea, fileFormat, screenFormat, mouseFormat, audioFormat, movieFolder);
		this.name = name;
	}

	//Hàm này bắt buộc để ghi đè custom lại hàm trong thư viên viết sẵn
	@Override
	protected File createMovieFile(Format fileFormat) throws IOException {

		if (!movieFolder.exists()) {
			movieFolder.mkdirs();
		} else if (!movieFolder.isDirectory()) {
			throw new IOException("\"" + movieFolder + "\" is not a directory.");
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH-mm-ss");
		return new File(movieFolder,
				name + "-" + dateFormat.format(new Date()) + "." + Registry.getInstance().getExtension(fileFormat));
	}

	// Hàm Start record video
	public static void startRecord(String methodName) throws Exception {
		//Tạo thư mục để lưu file video vào
		File file = new File("./test-recordings/");
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		int width = screenSize.width;
		int height = screenSize.height;

		Rectangle captureSize = new Rectangle(0, 0, width, height);

		GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
				.getDefaultConfiguration();
		screenRecorder = new RecordVideo(gc, captureSize,
				new Format(MediaTypeKey, MediaType.FILE, MimeTypeKey, MIME_AVI),
				new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
						CompressorNameKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, DepthKey, 24, FrameRateKey,
						Rational.valueOf(15), QualityKey, 1.0f, KeyFrameIntervalKey, 15 * 60),
				new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, "black", FrameRateKey, Rational.valueOf(30)),
				null, file, methodName);
		screenRecorder.start();
	}

	// Stop record video
	public static void stopRecord() throws Exception {
		screenRecorder.stop();
	}

	
	
	// ------Record with ATU library-----------
	public static ATUTestRecorder recorder;
	static DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH-mm-ss");
	static Date date = new Date();

	public static void startRecordATU(String videoName) throws Exception {
		recorder = new ATUTestRecorder("./test-recordings/", videoName + "-" + dateFormat.format(date), false);
		recorder.start();
	}

	public static void stopRecordATU() throws Exception {
		recorder.stop();
	}
}


Khi qua Test Case thì dùng thằng nào gọi cặp start và stop tương ứng thôi.

Vậy là xong rồi.

Teacher

Teacher

Anh Tester

Software Tester

Đường dẫu khó chân vẫn cần bước đi
Đời dẫu khổ tâm vẫn cần nghĩ thấu

Cộng đồng Automation Testing Việt Nam:


🌱 Zalo
Automation Testing:   https://zalo.me/g/lsxswc560
🌱 Facebook Group: Cộng đồng Automation Testing Việt Nam (Website, Desktop, Mobile)
🌱 Facebook Fanpage: Cộng đồng Automation Testing Việt Nam - Selenium

Chia sẻ khóa học lên trang

Bạn có thể đăng khóa học của chính bạn lên trang Anh Tester để kiếm tiền

Danh sách bài học