Java自動化環境搭建筆記(1)


Java自動化環境搭建筆記(1)


先搭建java接口測試的環境:

  • 使用mvn命令構建項目
  • 測試集通過testNG.xml組織並運行
  • 測試數據解耦,通過Excel等文件提供
  1. 基礎依賴
    • 創建maven項目(包含一些基礎的插件,見pom.xml)
    • 引入testNG測試框架
    • 引入allure報告框架
    • 其他日志等依賴引入
  2. 測試依賴待開發
    • 測試基類(統一數據提供方法)
    • Excel讀取工具類
    • 注解與監聽類

 

 

1. 基礎環境

  • java版本:1.8.0_191
  • IDEA
  • maven:Apache Maven 3.6.0
  • allure2:2.10.0

allure安裝

  • 隨項目一起放到項目根目錄.allure目錄,可以參考官方給出的項目示例:參考地址
  • allure2可以直接去官方github下載:下載地址

2. 項目結構

 

項目目錄
項目目錄

 

3. 代碼開發

3.1 Excel讀取

Excel讀取直接按照規定的方法讀取數據:

  1. 未指定sheet,默認讀取Sheet1。
  2. 指定Sheet名稱讀取到無空白標題或空白行隔斷的所有數據。
  3. 指定Sheet名稱與locate(一個定位器,也就是一個cell的值),從這個cell開始讀取到無空白標題或空白行隔斷的所有數據。
  4. 指定Name讀取Name區域的所有數據。name就是Excel的名稱,需要工作簿范圍的名稱
  5. 所有讀取方式都會默認跳過定位到的區域前兩行。如:name定位到第2行第2列開始,會從第2行為可備注等隨意填寫數據區域,第3行為列名,第四行開始為數據。

name定義方法:

  1. 選中區域,鼠標右鍵定義名稱,
  2. 公式 -> 名稱管理器 -> 新建

定義的名稱可左上角點擊直接跳到指定區域,或通過名稱管理器

 

查看名稱
查看名稱

 

 

默認Sheet1
默認Sheet1

 

 

指定Sheet讀取
指定Sheet讀取

 

 

指定name讀取
指定name讀取

 

 

指定locate讀取
指定locate讀取

 

package per.hao.utils;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ExcelReader implements Iterator<Object[]> {

    private static final Logger logger = LoggerFactory.getLogger(ExcelReader.class);

    private static final char[] LETTER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

    private InputStream in = null;
    private Workbook workbook = null;
    private Sheet sheet = null;

    /* 當前行id 列id */
    private int curRowNum = 1;
    private int curColNum = 0;

    /* 當前工作表中可讀最大行 */
    private int maxRowNum = 0;
    private int maxColNum = 0;

    /* 讀取行列數量記錄 */
    private int readRowNum = 0;
    private int readColNum = 0;

    /* 列名記錄 */
    List<String> colNames = new ArrayList<>();


    /** * 根據sheetName初始化 * * @param filePath excel文件路徑 * @param sheetName 讀取的sheet名稱 * */
    public static ExcelReader getDataBySheetName(String filePath, String sheetName) {
        return new ExcelReader(filePath, sheetName, "", "", 1);
    }

    /** * 根據定位器初始化 * * @param filePath excel文件路徑 * @param sheetName 讀取的sheet名稱 * @param locate 定位器名稱 * */
    public static ExcelReader getDataByLocate(String filePath, String sheetName, String locate) {
        return new ExcelReader(filePath, sheetName, locate, "", 2);
    }

    /** * 根據名稱初始化 * * @param filePath excel文件路徑 * @param Name 名稱 * */
    public static ExcelReader getDataByName(String filePath, String Name) {
        return new ExcelReader(filePath, "", "", Name, 3);
    }


    /** * 私有構造方法 * * @param filePath excel文件路徑 * @param sheetName 讀取的sheet名稱 * @param locate 定位器名稱 * @param name 名稱 * @param type 初始化的類型 * * 根據type的值來確定初始化的方法 * 1 : 根據sheetName初始化, filePath、sheetName不為空 * 2 : 根據定位器初始化, filePath、sheetName、 locate不為空 * 3 : 根據名稱初始化, name不為空 * */
    private ExcelReader(String filePath, String sheetName, String locate, String name, int type) {
        initWorkBook(filePath);
        if (type == 1) {// 根據sheetName初始化
            initSheet(filePath, sheetName);
            initParam();
            ininColumnName();
        } else if (type == 2) {// 根據定位器初始化
            initSheet(filePath, sheetName);
            initParam();
            registerLocate(locate);
            ininColumnName();

        } else if (type == 3) {// 根據名稱初始化
            initByName(filePath, name);
        }
    }

    /** * 根據名稱初始化當前讀取區域定位信息 * * @param filePath excel路徑 * @param designation 名稱 * * 讀取到的名稱需要是工作簿作用范圍,匹配定位信息初始化curColNum、 curRowNum、maxColNum、maxRowNum * */
    private void initByName(String filePath, String designation) {
        Name name = workbook.getName(designation);
        if (name != null) {
            initSheet(filePath, name.getSheetName());

            /* 根據excel定位字符串初始化名稱區域 */
            Matcher matcher = Pattern.compile("^.*?\\$(\\w+)\\$(\\d+):\\$(\\w+)\\$(\\d+)$")
                    .matcher(name.getRefersToFormula());
            if (matcher.find()) {
                curColNum = letterToDec(matcher.group(1));
                curRowNum = Integer.parseInt(matcher.group(2));
                maxColNum = letterToDec(matcher.group(3));
                maxRowNum = Integer.parseInt(matcher.group(4));
            } else {
                logger.error("cannot find coordinate: {}", name.getRefersToFormula());
            }

            ininColumnName();

        } else {
            logger.error("cannot find name: {}", designation);
        }

    }

    /** * 將Excel列定位字母轉換為數字 * 從0開始,A -> 0, AA -> 26, BA -> 53以此類推, 也就是特殊的26進制 * * @param letterCoordinate 列 * * @return int * */
    private int letterToDec(String letterCoordinate) {
        char[] cs = letterCoordinate.toCharArray();
        int decIndex = 0, i = 0;

        for (; i < cs.length; i++) {
            decIndex += Math.pow(26, (cs.length - i - 1)) * (Arrays.binarySearch(LETTER, cs[i]) + 1);
        }

        return decIndex - 1;// 從0開始 減1
    }

    /** * 初始化列名 * */
    private void ininColumnName() {
        Row colNameRow = sheet.getRow(curRowNum);

        /* 遇到空的cell讀取結束 */
        for (int i = 0; i < colNameRow.getLastCellNum(); i++) {
            String cellContents = getCellContents(colNameRow.getCell(i));
            if (!"".equals(cellContents)) {
                colNames.add(cellContents);
            } else {
                logger.debug("Read to blank cell default read column end");
                break;
            }
        }
        curRowNum ++;
    }


    /** * 根據定位器初始化當前行 * * @param locate 定位器 * */
    private void registerLocate(String locate) {
        /* 至少存在1列 */
        if (maxColNum >= 1) {
            boolean flag = false;// 默認無定位器

            for (int i = 0; i < sheet.getLastRowNum(); i++) {
                Row row = sheet.getRow(i);

                if (row == null) { continue; }

                Cell cell = row.getCell(0);

                /* 找到定位器,初始化當前讀取位置 */
                if (locate.equals(getCellContents(cell))) {
                    flag = true;
                    curRowNum = cell.getAddress().getRow() + 1;// 從定位器下一行開始
                }

                if (flag) {
                    logger.info("find locate point, read from next line");
                } else {
                    logger.info("cannot find locate point, read from default line");
                }
            }
        }

    }

    /** * 初始化部分變量 * * */
    private void initParam() {
        maxRowNum = sheet.getLastRowNum() + 1;
        maxColNum = sheet.getLastRowNum();
        readColNum = colNames.size();
    }

    /** * 根據Sheet名稱獲取Sheet * * @param sheetName sheet名稱 * */
    private void initSheet(String filePath, String sheetName) {
        /* 獲取WorkBook 中的sheet */
        if (workbook != null) {
            sheet = workbook.getSheet(sheetName);
        } else {
            logger.error("WorkBook Object dose not exist!");
        }

        /* sheet未獲取到 */
        if (sheetName == null) {
            logger.error("In {} sheet does not exist", filePath);
        } else {
            logger.info("read sheet: {}", sheetName);
        }
    }

    /** * 根據后綴判斷版本獲取excel對象 * * @param filePath 文件路徑 * */
    private void initWorkBook(String filePath) {
        try {
            in = new BufferedInputStream(new FileInputStream(filePath));
        /* 2003 Excel */
        if (filePath.endsWith(".xls")) {
            workbook = new HSSFWorkbook(in);
        /* 2007 Excel */
        } else if (filePath.endsWith(".xlsx")) {
            workbook = new XSSFWorkbook(in);
        } else {
            logger.error("File is not Excel File: {}", filePath);
        }
        } catch (FileNotFoundException e) {
            logger.error("File not found: ", e);
        } catch (IOException e) {
            logger.error("Create WorkBook failed: ", e);
        }

        // 設置默認返回空串
        workbook.setMissingCellPolicy(Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
        logger.info("read excel: {}", filePath);
    }

    /** * 判斷是否為空行 * */
    private boolean judgeblankRow(Row row) {
        for (int i = 0; i < row.getLastCellNum(); i++) {
            Cell cell = row.getCell(i);
            /* 存在單元格不為空字符串則為非空行 */
            if (!"".equals(getCellContents(cell))) {
                return false;
            }
        }
        return true;
    }

    /** * 關閉資源 * */
    private void close() {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                logger.error("close file filed", e);
            }
        }
    }

    /** * 判斷是否存在下一行 * * 如果下一行為空行 @return true * 如果下一行為非空行 @return false * */
    @Override
    public boolean hasNext() {
        if (curRowNum < maxRowNum) {
            Row curRow = sheet.getRow(curRowNum);
            if (judgeblankRow(curRow)) {
                return false;
            }
            return true;
        }
        return false;
    }

    /** * 獲取下一行數據 * * @return Object[]數組對象 * */
    @Override
    public Object[] next() {
        Map<String, String> curRowData = new HashMap<>();

        Row curRow = sheet.getRow(curRowNum);
        /* 根據列名取對應列數據 */
        for (int i = curColNum; i < colNames.size(); i++) {
            Cell cell = curRow.getCell(i);
            curRowData.put(colNames.get(i), getCellContents(cell));
        }

        readRowNum ++;
        curRowNum ++;

        return new Object[] { curRowData };
    }

    /** * 以String類型返回值 * * */
    private String getCellContents(Cell cell) {
        cell.setCellType(CellType.STRING);
        return cell.getStringCellValue();
    }

    @Override
    public void remove() {
        logger.error("not support remove");
    }
}

3.2 數據提供與監聽器

  1. testNG提供了DataProvider注解來指定數據提供接口,這里定義一個BaseTester類添加一個公共的getData方法作為公共的數據提供接口。
  2. 讀取數據需要指定dataProvider="名稱",使用監聽器將dataProvider指定為默認的。
  3. 定義自己的DataSource注解,定義文件路徑、sheetName等參數,在getData方法被調用的時候解釋DataSource注解內參數來去讀指定數據。

3.2.1 BaseTester測試基類

在測試類中extends BaseTester

package per.hao;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.DataProvider;
import per.hao.annotations.DataSource;
import per.hao.utils.DataSourceType;
import per.hao.utils.ExcelReader;

import java.io.File;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.regex.Matcher;


public class BaseTester {

    public static final Logger logger =
            LoggerFactory.getLogger(BaseTester.class);

    /** * 數據提供公共接口 * */
    @DataProvider(name = "getData")
    public static Iterator<Object[]> getData(Method method) {

        DataSource dataSource = null;

        /** 數據源注解存在判斷 */
        if (method.isAnnotationPresent(DataSource.class)) {
            dataSource = method.getAnnotation(DataSource.class);
        } else {
            logger.error("未指定@DataSource注解卻初始化了dataProvider");
        }

        /** 根據數據源類型返回對應數據迭代器 */
        if (DataSourceType.CSV
                .equals(dataSource.dataSourceType())) {

            // CSVReader

        } else if (DataSourceType.POSTGRESQL
                .equals(dataSource.dataSourceType())) {

            // PostgresqlReader

        }

        /* 默認讀取excel */
        // 根據名稱
        if (!"".equals(dataSource.name())) {

            return ExcelReader.getDataByName(
                    dealFilePath(dataSource.filePath()), dataSource.name());
            // 根據錨點
        } else if (!"".equals(dataSource.locate())) {

            return ExcelReader.getDataByLocate(
                    dealFilePath(dataSource.filePath()), dataSource.sheetName(), dataSource.locate());
           // 讀取整個sheet頁
        } else {

            return ExcelReader.getDataBySheetName(
                    dealFilePath(dataSource.filePath()), dataSource.sheetName());

        }
    }

    /** * 如果只存在文件名,則拼接默認讀取目錄,否則使用指定的路徑 * * @param filePath 文件路徑 * */
    private static String dealFilePath(String filePath) {
        if (!filePath.matches(".*[/\\\\].*")) {
            filePath = "src/test/resources/data/" + filePath;
        }

        return new File(filePath.replaceAll("[/\\\\]+",
                Matcher.quoteReplacement(File.separator))).getAbsolutePath();
    }
}

3.2.2 DataSourceListener監聽器

  1. DataSourceListener
package per.hao.listener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;
import per.hao.BaseTester;
import per.hao.annotations.DataSource;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/** * 監聽測試是否存在{@code DataSource.CLASS}注解: * 1. 如果存在@DataSource注解且@Test注解中未對dataProvider賦值 * 則指定{@code BaseTester.CLASS}中提供的getData數據提供者方法 * 2. 如果不存在@DataSource注解或@Test注解中已經對dataProvider賦值 * 則不修改dataProvider * * 測試方法@Test注解dataProviderClass如果值為Object.class則修改 * 為BaseTest.class * */
public class DataSourceListener implements IAnnotationTransformer {

    private static final Logger logger = LoggerFactory.getLogger(DataSourceListener.class);

    /** * 本監聽的入口,監聽每次測試方法的調用,並設置相應參數 * * @param iTestAnnotation 提供對@Test注解操作的對象 * @param aClass * @param constructor * @param method 本次觸發監聽的測試方法 * */
    @Override
    public void transform(ITestAnnotation iTestAnnotation, Class aClass, Constructor constructor, Method method) {
        // 測試為null
        if (iTestAnnotation == null || method == null) {
            return;
        }

        /** 判斷並修改@Test注解 dataProvider 值 */
        modifyDataProvider(iTestAnnotation, method);

        /** 判斷並修改@Test注解 dataProviderClass 值 */
        if (iTestAnnotation.getDataProviderClass() == null) {
            iTestAnnotation.setDataProviderClass(BaseTester.class);
            logger.debug("dataProviderClass設置為: {}", BaseTester.class);
        } else {
            logger.debug("dataProviderClass已經指定: {}", iTestAnnotation.getDataProviderClass());
        }
    }

    /** * 對@Test注解dataProvider數據提者判斷修改的方法 * * @param iTestAnnotation 提供對@Test注解操作的對象 * @param method 本次觸發監聽的測試方法 * */
    private void modifyDataProvider(ITestAnnotation iTestAnnotation, Method method) {

        /** 如果存在@DataSource注解 */
        if (method.isAnnotationPresent(DataSource.class)) {
            if ("".equals(iTestAnnotation.getDataProvider())) {
                iTestAnnotation.setDataProvider("getData");
                logger.debug("dataProvider設置為: getData");
            } else {
                logger.debug("dataProvider已指定: {}", iTestAnnotation.getDataProvider());
            }

        /* 未指定@DataSource注解卻指定了dataProvider */
        } else if ((! method.isAnnotationPresent(DataSource.class)) &&
                ! "".equals(iTestAnnotation.getDataProvider())) {
            logger.error("未指定@DataSource注解卻初始化了dataProvider");
        }
    }
}
  1. 將監聽器配置到testNG.xml中
    <listeners>
        <!-- 數據源監聽(修改@Test注解中的部分配置) -->
        <listener class-name="per.hao.listener.DataSourceListener"/>
    </listeners>

3.2.3 DataSource數據源注解

SQL與CSV方法目前沒有寫,先只寫了Excel數據讀取的工具類

package per.hao.annotations;

import per.hao.utils.DataSourceType;

import java.lang.annotation.*;

/** * 標注參數化數據源, 默認從提供Excel讀取 * */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataSource {

    DataSourceType dataSourceType() default DataSourceType.EXCEL;

    String filePath() default "";

    String sheetName() default "Sheet1";// 除根據name外需要指定, 默認讀取Sheet1

    String locate() default "";// 定位器, 左上角第一個cell(ReadExcel用)

    String name() default ""; // 可指定Excel名稱讀取

    String sql() default "";

}

4. 配置

4.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>per.hao</groupId>
    <artifactId>selenium-project-hzhang</artifactId>
    <version>1.0.0</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <allure.version>2.10.0</allure.version>
        <java.version>1.8</java.version>
        <aspectj.version>1.9.2</aspectj.version>
    </properties>

    <dependencies>

        <!-- testNG框架 -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.14.3</version>
            <scope>test</scope>
        </dependency>

        <!-- allure報告依賴 -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-testng</artifactId>
            <version>${allure.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-maven</artifactId>
            <version>${allure.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-all</artifactId>
            <version>1.3</version>
            <scope>test</scope>
        </dependency>

        <!-- 日志依賴 -->
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
            <scope>test</scope>
        </dependency>

        <!-- excel讀取插件 -->
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.0</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.0</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.1</version>
                <configuration>
                    <argLine>
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    </argLine>
                    <!-- 測試失敗繼續運行 -->
                    <testFailureIgnore>true</testFailureIgnore>
                    <!-- testNG用例集xml設置 -->
                    <suiteXmlFiles>
                        <suiteXmlFile>
                            src/test/resources/testng/testNG.xml
                        </suiteXmlFile>
                    </suiteXmlFiles>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjweaver</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>

            <!-- 構建插件, 指定版本與編碼 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>

        </plugins>
    </build>

    <reporting>
        <excludeDefaults>true</excludeDefaults>
        <plugins>
            <plugin>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-maven</artifactId>
                <version>${allure.version}</version>
                <configuration>
                    <reportVersion>${allure.version}</reportVersion>
                </configuration>
            </plugin>
        </plugins>
    </reporting>
</project>

4.2 allure.properties

allure.results.directory=target/allure-results
allure.link.issue.pattern=https://example.org/issue/{}
allure.link.tms.pattern=https://example.org/tms/{}

4.3 log4j.properties

log4j.rootLogger=CONSOLE,FILE
log4j.addivity.org.apache=false

# 應用於控制台
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=DEBUG
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.Encoding=UTF-8
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d - %c -%-4r [%t] %-5p - %m%n

# 每天新建日志
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=E:/log4j/log
log4j.appender.A1.Encoding=UTF-8
log4j.appender.A1.Threshold=DEBUG
log4j.appender.A1.DatePattern='.'yyyy-MM-dd
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L : %m%n

#應用於文件
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=E:/log4j/file.log
log4j.appender.FILE.Threshold=DEBUG
log4j.appender.FILE.Append=true
log4j.appender.FILE.Encoding=UTF-8
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d - %c -%-4r [%t] %-5p - %m%n

4.4 testNG.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="MyProjectSuite" parallel="classes" thread-count="1">
    <test verbose="2" preserve-order="true" name="測試獲取數據">
        <classes>
            <class name="per.hao.cases.SimpleTest" />
        </classes>
    </test>

    <listeners>
        <!-- 數據源監聽(修改@Test注解中的部分配置) -->
        <listener class-name="per.hao.listener.DataSourceListener"/>
    </listeners>
</suite> <!-- Suite -->

5. 測試示例

5.1 SampleTest

package per.test;

import io.qameta.allure.*;
import org.testng.annotations.Test;
import per.hao.annotations.DataSource;
import java.util.Map;
import static io.qameta.allure.Allure.*;


public class SimpleTest extends DataSourceListener{

    @Test(description = "測試默認讀取Sheet1")// 這個desciption是標題
    @Severity(SeverityLevel.CRITICAL)// 測試優先級
    @DataSource(filePath = "param.xlsx")
    @Description("在不指定Sheet名稱的情況下,測試能否讀取默認數據。")// 這個才是描述
    @Step("第一步先測試一下能否讀取Sheet1中的數據")// 父步驟
    @Link(name = "默認讀取Sheet1需求", url = "https://www.cnblogs.com/h-zhang/")// 需求
    @Issue("https://www.cnblogs.com/h-zhang/")// BUG
    public void simpleTest1(Map<String, String> row) {

        step("step 1: 獲取用例數據");
        String caseName = row.get("用例名稱");

        step("step 2: 返回實際結果" + caseName);
    }

    @Test(description = "測試指定Sheet名稱讀取")
    @DataSource(filePath = "param.xlsx", sheetName = "Sheet讀取")
    public void simpleTest2(Map<String, String> row) {
        step("step 1: 獲取用例數據");
        String caseName = row.get("用例名稱");

        step("step 2: 返回實際結果" + caseName);
    }

    @Test(description = "測試指定名稱讀取")
    @DataSource(filePath = "param.xlsx", name = "測試name讀取")
    public void simpleTest3(Map<String, String> row) {
        step("step 1: 獲取用例數據");
        String caseName = row.get("用例名稱");

        step("step 2: 返回實際結果" + caseName);
    }

    @Test(description = "測試指定locate讀取")
    @DataSource(filePath = "param.xlsx", sheetName = "locate讀取", locate = "I'm locate")
    public void simpleTest4(Map<String, String> row) {
        step("step 1: 獲取用例數據");
        String caseName = row.get("用例名稱");

        step("step 2: 返回實際結果" + caseName);
    }
}

5.2 測試運行

項目根目錄下打開命令行:

# 1. 運行測試
mvn clean test site
# 2. 生成報告
mvn io.qameta.allure:allure-maven:serve

5.3 報告示例

概覽有地方沒數據是因為沒有歷史記錄,使用jenkins運行持續集成運行幾次就有了。

 

概覽
概覽

 

 

按測試集查看
按測試集查看

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM