I. Log4j Logging
1. Log4j Logging là gì ?
- Thông thường chúng ta hay sử dụng system.out.println() để in ra màn hình tình trạng, thông tin hệ thống tại 1 thời điểm nào đó, tuy nhiên đó không phải giải pháp, bởi vì automation nó chạy một cách tự động, chúng ta không thể lúc nào cũng in ra màn hình để xem được, cho nên là chúng ta phải ghi các cái log vào một file log. Để ghi log vào trong log chúng ta dùng thư viện log4j2. Log4j2 là một API ghi lại log cực kỳ hữu dụng có trên nền tảng Java và .Net framework.
2. Cài đặt và sử dụng Log4j
- Tại thời điểm viết bài viết này phiên bản của log4j2 hiện là: apache-log4j-2.14.1-bin.zip, tôi sẽ để link trang download TẠI ĐÂY, các bạn có thể download file mới hơn khi có update khi các bạn đọc được bài viết tại thời điểm sau này. Sau khi download chúng ta sẽ giải nén ra 1 folder, chúng ta có thể thấy nó chứa rất nhiều file jar, tuy nhiên công việc của chúng ta chỉ cần đó là ghi log vào trong 1 file, nên 2 file chúng ta cần đó là: log4j-api-2.14.1.jar và log4j-core-2.14.1.jar, chúng ta chỉ cần import 2 cái file này trong buildpath của chúng ta thôi, không nên import tất cả các thư viện trong file giải nén vừa rồi vào nó sẽ gây conflict.
Hình 2: Trang web download thư viện Log4j2
- Tiếp đó chúng ta phải có thêm 1 file setting log4j2.xml này các bạn có thể download TẠI ĐÂY, các bạn lưu ý là tên file này không được đổi, phải chính xác như vậy, khi dùng chúng ta sẽ copy vào folder bin của project của chúng ta.
- Trong file log4j2.xml nó sẽ có những thông tin như sau: Nó sẽ khai báo 2 thứ đó là Appenders và Loggers, Appenders là đầu ra của log chúng ta, ở đây đầu ra sẽ có 2 cái đó là file và STOUT, STOUT là ghi ra màn hình, nếu chúng ta chỉ muốn ghi log ra file thôi thì chúng ra chỉ cần khai báo mỗi dòng <File name="file" fileName="log4jTest.log" append="true">, fileName chính là tên file log của chúng ta, ở trong ví dụ này chúng ta sẽ ghi log vào file log4jTest.log ở trong root folder của project, ở đây có tham số append, nếu chúng ta khai báo append="true" thì khi file đó đã có dữ liệu nó sẽ ghi tiếp vào cuối file, còn nếu chúng ta khai báo append="false" thì nó sẽ ghi đè lên dữ liệu đã có, tiếp đó là cái <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> đây là cái định dạng mà log chúng ta viết vào như thế nào, ở ví dụ này nó là 1 cái định dạng PatternLayout chuẩn, còn ý nghĩa của từng tham số chúng ta có thể xem TẠI ĐÂY nó sẽ giải thích toàn bộ ý nghĩa tham số của cái PatternLayout này. Thông thường chúng ta chỉ sử dụng cái pattern layout chuẩn.
- Hình 2 là minh họa cho 1 file log được ghi bằng log4j2, chúng thấy đầu tiên nó sẽ là ngày, giờ, phút, giây, phần trăm giây, rồi đến log level, nó có các loại log level đó là INFO, WARN, ERROR, FATAL, DEBUG, tiếp đó là cái log này được gọi đến từ method nào, class nào dòng code nào, ở trong hình 2 đó là hàm main, và cuối cùng là nội dung của file log đó là gì.
- Nguyên tắc đó là log4j2 nó sẽ tìm setting của nó ở trong file log4j2.xml và tìm ở trong cái setting ở cái class patch của project mà folder bin nó lại ở trong class patch chúng ta chỉ cần copy file log4j2.xml vào file folder bin là được. Có 1 số tài liệu bảo là copy trong folder source cũng được nhưng mình đã từng thử rất nhiều lần nhưng nó không có nhận.
- Loggers nó sẽ khai báo cái AppenderRef , trong ví dụ phía dưới chúng ta có 2 cái appenders ref đó là file và STDOUT và cái level của cái file ta để là INFO, còn level của cái STOUT ta để là DEBUG, INFO và DEBUG nó khác nhau ở chỗ, cái INFO nó sẽ in ra các cái log level không phải là debug, chỉ có cái nào có log level là debug thì nó mới in ra debug thôi, bình thường thì đối với phía khách hàng thì sẽ không cho nhìn thấy log level là debug còn nếu developer họ debug thì nó mới cần cái log level là debug nên là tùy theo cơ chế set log level là gì chúng ta nên nhìn thấy cái log tương ứng.
- Để sử dụng được log4j chúng ta phải khai báo một cái logger, ở mỗi class cần ghi log chúng ta sẽ phải khai báo một cái logger ở trong class đó, chúng ta sẽ khai báo bằng cách Logger logger = LogManager.getLogger(tên class mà cần chạy.class), để ghi log chúng ta sẽ gọi đến, logger.info("This is info log"); logger.warn("This is warn log"); logger.error("This is error log"); logger.fatal("This is fatal log"); hay logger.debug("This is debug log"); lúc nào nó sẽ ghi vào cái log appenders tương ứng như hình 2.
- Với mỗi class của chúng ta chúng ta phải khai báo 1 cái logger thì điều đó hơi bất tiện vì vậy thông thường chúng ta sẽ tạo ra 1 cái gọi là logUtil, tuy nhiên cái này nó có một cái không hay đó là cái địa chỉ gọi đến nó luôn luôn là logUtil, chúng ta sẽ không biết được dòng code nào gọi đến cái log này. chúng ta sẽ khồng thể biết được cái class nào đã gọi ra dòng log đó, nhưng đôi khi chúng ta chỉ quan tâm đến nội dung log rồi ngày giờ các thứ... thì chúng ta có thể sử dụng thông qua logUtil này.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="file" fileName="log4jTest.log" append="true">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</File>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="file" level="INFO"/>
<AppenderRef ref="STDOUT" level="DEBUG"/>
</Root>
</Loggers>
</Configuration>
II. Đọc và ghi dữ liệu từ file Excel
- Thông thường trong data driven chúng ta sẽ đọc data từ external data source ví dụ như là excel, csv, database, thì chúng ta rất hay làm việc với file excel
- Để làm việc với file excel chúng ta sẽ sử dụng thư viện apache poi, các bạn có thể download TẠI ĐÂY, tại thời điểm mình viết bài viết này poi đang ở phiên bản 5.0 chúng ta sẽ download file poi-bin-5.0.0-20210120.zip về, sau khi download về thì chúng ta sẽ giải nén ra 1 folder, trong folder poi chúng ta sẽ thấy các thư viện ở bên ngoài và trong các folder như auxiliary, lib, ooxml-lib, trong doc không có thư viện gì cả thì chúng ta phải import tất cả các thư viện này vào build patch của project chúng ta.
- Để làm việc với file Excel thì chúng ta sử dụng excel util, chúng ta tạo ra cái package là Utils trong source folder, vì chúng ta có sử dụng thêm cả LogUtil nên trong này chúng ta sẽ copy file LogUtil.java ExcelUtils.java vào trong folder Utils của project của chúng ta , các bạn download file đó TẠI ĐÂY , chúng ta copy file log4j2.xml vào folder bin của project, sau đó refresh lai project sẽ thấy 2 file này xuất hiện.
Giải thích code trong file ExcelUtils.java
- LogUtil.java là để quản lý log rồi, còn file ExcelUtils là cái công cụ giúp chúng ta làm việc với file excel hiệu quả hơn, cái poi cung cấp cho chúng ta một cơ chế để làm việc với file excel thông qua XSSFSheet, XSSFWorkbook, XSSFCell, XSSFRow, thì cái XSSFWorkbook là để chúng ta mở ra 1 cái file excel, XSSFSheet là mở ra 1 cái sheet trong file excel đó, còn cái XSSFCell là để mở ra 1 ô trong file excel, còn cái XSSFRow là cái để làm việc với 1 cái hàng trong file excel, ở đây chúng ta sẽ có 1 hàm khởi tạo ExcelUtils(String Path, String SheetName) trong hàm này thì chúng ta sẽ truyền vào đường dẫn tới file excel đó và tên của cái sheet chúng ta muốn mở ra, trong này chúng ta sẽ mở các file excel này ra vào gán vào file excel workbook, tiếp đến chúng ra dùng ExcelWBook.getSheet(SheetName); để load cái sheet này vào excelwork sheet, đồng thời lưu lại đường dẫn trong file excel để nó sẽ dụng trong cái method để save cái file excel này lại.
- Tiếp đến là hàm getCellData() hàm này mục tiêu của nó là để nó đọc một cái cell thì file excel ra, ở đây chúng ta đọc ra dưới dạng String, nó sẽ truyền vào số dòng và số cột của cell đó, và gán Cell = ExcelWSheet.getRow(RowNum) để đọc dòng đó ra, sau đó .getCell(ColNum) để đọc cái cell đó ra, sau đó nó gọi đến hàm Cell.getStringCellValue(); để mà nó đọc cái cell đó ra dưới dạng String và return về cái cellData, nếu cell chúng ta không phải dạng String thì chúng ta thấy nó có thêm một số loại get khác như getDateCellValue() nó sẽ đọc ra dưới dạng kiểu Date, getNumericCellValue() nó sẽ đọc cell này ra dưới dạng số double, thì thông thường chỉ dùng getStringCellValue(), nếu như các dữ liệu của chúng ta ở trong file nó là các số, thì chúng ta sẽ thêm dấu nháy ở đằng trước để nó đọc ra dưới dạng String, còn không thêm dấu nháy vào nó sẽ bị lỗi.
- Tiếp theo là hàm setCellData() nó sẽ ghi data vào trong 1 cái cell, đầu tiên phải tìm đến cái cell đó bằng cách Row = ExcelWSheet.getRow(RowNum); Cell = Row.getCell(ColNum); nếu cell này bằng null chưa tồn tại thì chúng ta phải khởi tạo cái cell này đã sau đó mới ghi vào được, sau đó phải save file này lại chúng ta fileOut.flush(); fileOut.close(); thì nó mới ghi vào file excel này được. Excel Path sẽ được sử dụng để chúng ta lưu lại đường dẫn của file excel.
- Tiếp đó là hàm getRowUsed() sẽ trả về số dòng tối đa của file excel thông qua cái ExcelWSheet.getLastRowNum() , chúng ta sử dụng cái này để biết file excel của chúng ta có bao nhiêu dòng
- Tiếp đó là hàm getRowContains() hàm này được tạo ra để mục đích sử dụng trong trường hợp muốn tìm đến cái dòng nào mà chứa cái testcase name ấy thì nó trả về chúng ta dùng đấy, còn không tìm thấy nó sẽ trả về dòng cuối cùng
- Tiếp đến là hàm getTableArray(), hàm này sử dụng để support cho data provider của NG Framework, chúng ta truyền vào số cột muốn đọc, và nó đọc toàn bộ data và lưu vào trong một cái mảng object vì data provider của testNG framework nó yêu cầu truyền vào cái mảng object nên cái hàm này nó sẽ trả về cho ta cái mảng object.
Nội dung file ExcelUtils:
package utils;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelUtils {
private XSSFSheet ExcelWSheet;
private XSSFWorkbook ExcelWBook;
private XSSFCell Cell;
private XSSFRow Row;
private String ExcelPath;
// This method is to set the File path and to open the Excel file, Pass
// Excel Path and Sheetname as Arguments to this method
public ExcelUtils(String Path, String SheetName) throws Exception {
try {
// Open the Excel file
FileInputStream ExcelFile = new FileInputStream(Path);
ExcelPath = Path;
// Access the required test data sheet
ExcelWBook = new XSSFWorkbook(ExcelFile);
ExcelWSheet = ExcelWBook.getSheet(SheetName);
LogUtil.info("Excel sheet opened");
//System.out.println("Excel sheet opened");
} catch (Exception e) {
throw (e);
}
}
// This method is to read the test data from the Excel cell, in this we are
// passing parameters as Row num and Col num
public String getCellData(int RowNum, int ColNum) throws Exception {
try {
Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
String CellData = Cell.getStringCellValue();
return CellData;
} catch (Exception e) {
return "";
}
}
public double getNumberCellData(int RowNum, int ColNum) throws Exception {
try {
Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
double CellData = Cell.getNumericCellValue();
return CellData;
} catch (Exception e) {
return 0;
}
}
// This method is to write in the Excel cell, Row num and Col num are the
// parameters
@SuppressWarnings("static-access")
public void setCellData(String data, int RowNum, int ColNum)
throws Exception {
try {
Row = ExcelWSheet.getRow(RowNum);
Cell = Row.getCell(ColNum);
if (Cell == null) {
Cell = Row.createCell(ColNum);
Cell.setCellValue(data);
} else {
Cell.setCellValue(data);
}
// Constant variables Test Data path and Test Data file name
FileOutputStream fileOut = new FileOutputStream(ExcelPath);
ExcelWBook.write(fileOut);
fileOut.flush();
fileOut.close();
} catch (Exception e) {
throw (e);
}
}
public int getRowContains(String sTestCaseName, int colNum) throws Exception {
int i;
try {
int rowCount = getRowUsed();
for (i = 0; i < rowCount; i++) {
if (getCellData(i, colNum).equalsIgnoreCase(
sTestCaseName)) {
break;
}
}
return i;
} catch (Exception e) {
LogUtil.error(e.getMessage());
//System.out.println("Class ExcelUtil | Method getRowContains | Exception desc : "
// + e.getMessage());
throw (e);
}
}
public int getRowUsed() throws Exception {
try {
int RowCount = ExcelWSheet.getLastRowNum();
//System.out.println("Total number of Row used return as < " + RowCount + " >.");
return RowCount;
} catch (Exception e) {
LogUtil.error(e.getMessage());
throw (e);
}
}
public Object[][] getTableArray(int column)
throws Exception {
String[][] tabArray = null;
try {
int startRow = 1;
int startCol = 0;
int ci, cj;
int totalRows = ExcelWSheet.getLastRowNum();
// you can write a function as well to get Column count
int totalCols = column;
tabArray = new String[totalRows][totalCols];
ci = 0;
for (int i = startRow; i <= totalRows; i++, ci++) {
cj = 0;
for (int j = startCol; j < totalCols; j++, cj++) {
tabArray[ci][cj] = getCellData(i, j);
System.out.println(tabArray[ci][cj]);
}
}
}
catch (FileNotFoundException e) {
LogUtil.error("Could not read the Excel sheet");
//System.out.println("Could not read the Excel sheet");
e.printStackTrace();
}
catch (IOException e) {
LogUtil.error("Could not read the Excel sheet");
//System.out.println("Could not read the Excel sheet");
e.printStackTrace();
}
return (tabArray);
}
}
III. Đọc và ghi dữ liệu từ file CSV
Việc sử dụng file csv nó đơn giản hơn rất nhiều, chúng ta cũng sử dụng file CSVUtil.java
File này cũng có 1 hàm khởi tạo để đọc file csv, chúng ta truyền vào đường dẫn đến file csv và hàm khởi tạo này đọc file csv sau đó lưu vào list mảng string cứ mỗi một dòng của file csv thì nó sẽ là 1 list item, mỗi dòng sẽ gồm có 1 mảng string, mỗi string trong mảng string thì nó giống như 1 cell trong file excel, bởi vì file csv là một file text nên data nó cách nhau bởi dấu chấm phẩy, cho nên là ở đây chúng ta dùng file.readLine() để đọc dòng của file csv này vào sau đó dùng hàm record.split(",") để cắt theo cái dấu phẩy thì nó sẽ tách và lưu thành các mảng string và thêm vào trong list. Hàm getCellData(int row, int col) để đọc data tại các vị trí, hàm getRowUsed() để biết file của chúng ta có bao nhiêu dòng, file csv thông thường chỉ đọc data thôi chứ rất khó có thể ghi bào file csv nên sẽ không có hàm support ghi vào. Việc sử dụng file csv cũng sử dụng giống file excel.
package utils;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class CSVUtil {
public List<String[]> CSVList;
public CSVUtil(String fileName) throws IOException {
List<String[]> records = new ArrayList<String[]>();
String record;
BufferedReader file = new BufferedReader(new FileReader(fileName));
while ((record = file.readLine()) != null) {
String fields[] = record.split(",");
records.add(fields);
}
file.close();
CSVList = records;
}
public int getRowUsed() {
return CSVList.size();
}
public String getCellData(int row, int col) {
String[] data = CSVList.get(row);
return data[col];
}
}





0 Bình luận:
Đăng nhận xét