前言
在前面的幾篇文章中,我們介紹了從需求到設計,再到部分功能實現,本篇作爲完結篇,我們一起來完成剩下的功能實現,主要爲日誌管理和性能監控以及有同學提出測試用例多參數的問題。
走進Java接口測試之從0到1搭建數據驅動框架(需求篇)
走進Java接口測試之從0到1搭建數據驅動框架(設計篇)
走進Java接口測試之從0到1搭建數據驅動框架(用例管理)
走進Java接口測試之從0到1搭建數據驅動框架(多數據源和業務持久層)
日誌管理
一個成熟的數據驅動框架,日誌管理這個是必不可少的。在開發和調試階段,日誌可以幫助我們更快的定位問題;
SpringBoot 在所有內部日誌中使用 Commons Logging,但是默認配置也提供了對常用日誌的支持,如:Java Util Logging,Log4J, Log4J2 和 Logback。每種 Logger 都可以通過配置使用控制檯或者文件輸出日誌內容。
LogBack 和 Log4j 都是開源日記工具庫,而 LogBack 是 Log4j 的改良版本,比 Log4j 擁有更多的特性,同時也帶來很大性能提升,同時天然支持SLF4J。
LogBack 官方建議配合 Slf4j 使用,這樣可以靈活地替換底層日誌框架。所以在此處我們選擇了LogBack。
默認日誌框架Logback
默認情況下,SpringBoot 會用 Logback 來記錄日誌,並用 INFO 級別輸出到控制檯。在運行應用程序和其他例子時,我們可以看到很多 INFO 級別的日誌了。
從上圖可以看到,日誌輸出內容元素具體如下:
- 時間日期:精確到毫秒
- 日誌級別:ERROR, WARN, INFO, DEBUG or TRACE
- Logger名:通常使用源代碼的類名
- 分隔符:— 標識實際日誌的開始
- 進程 ID
- 線程名:方括號括起來(可能會截斷控制檯輸出)
- 日誌內容
實際開發中我們不需要直接添加 Logback 依賴,因爲 spring-boot-starter
其中包含了 spring-boot-starter-logging
,該依賴內容就是 SpringBoot 默認的日誌框架 logback。
<!--MyBatis、數據庫驅動、數據庫連接池、logback-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
SpringBoot 官方推薦優先使用帶有 -spring
的文件名作爲你的日誌配置(如使用logback-spring.xml
,而不是 logback.xml
),命名爲 logback-spring.xml
的日誌配置文件,springboot 可以爲它添加一些 springboot 特有的配置項(下面會提到)。並且放在 src/main/resources
下面即可。
添加配置文件 logback-spring.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日誌根目錄-->
<springProperty scope="context" name="LOG_HOME" source="logging.path" defaultValue="./logs/spring-boot-logback"/>
<!-- 日誌級別 -->
<springProperty scope="context" name="LOG_ROOT_LEVEL" source="logging.level.root" defaultValue="INFO"/>
<!-- 標識這個"STDOUT" 將會添加到這個logger -->
<springProperty scope="context" name="STDOUT" source="log.stdout" defaultValue="STDOUT"/>
<!-- 日誌文件名稱-->
<property name="LOG_PREFIX" value="api-test-logback" />
<!-- 日誌文件編碼-->
<property name="LOG_CHARSET" value="UTF-8" />
<!-- 日誌文件路徑+日期-->
<property name="LOG_DIR" value="${LOG_HOME}/%d{yyyyMMdd}" />
<!--對日誌進行格式化-->
<property name="LOG_MSG" value="- | [%d{yyyyMMdd HH:mm:ss.SSS}] | [%level] | [${HOSTNAME}] | [%thread] | [%logger{36}] | --> %msg|%n "/>
<!--文件大小,默認10MB-->
<property name="MAX_FILE_SIZE" value="50MB" />
<!-- 配置日誌的滾動時間 ,表示只保留最近 10 天的日誌-->
<property name="MAX_HISTORY" value="10"/>
<!--輸出到控制檯-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- 輸出的日誌內容格式化-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${LOG_MSG}</pattern>
</layout>
</appender>
<!--輸出到文件-->
<appender name="0" class="ch.qos.logback.core.rolling.RollingFileAppender">
</appender>
<!-- 定義 ALL 日誌的輸出方式:-->
<appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日誌文件路徑,日誌文件名稱-->
<File>${LOG_HOME}/all_${LOG_PREFIX}.log</File>
<!-- 設置滾動策略,當天的日誌大小超過 ${MAX_FILE_SIZE} 文件大小時候,新的內容寫入新的文件, 默認10MB -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日誌文件路徑,新的 ALL 日誌文件名稱,“ i ” 是個變量 -->
<FileNamePattern>${LOG_DIR}/all_${LOG_PREFIX}%i.log</FileNamePattern>
<!-- 配置日誌的滾動時間 ,表示只保留最近 10 天的日誌-->
<MaxHistory>${MAX_HISTORY}</MaxHistory>
<!--當天的日誌大小超過 ${MAX_FILE_SIZE} 文件大小時候,新的內容寫入新的文件, 默認10MB-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 輸出的日誌內容格式化-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${LOG_MSG}</pattern>
</layout>
</appender>
<!-- 定義 ERROR 日誌的輸出方式:-->
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 下面爲配置只輸出error級別的日誌 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<OnMismatch>DENY</OnMismatch>
<OnMatch>ACCEPT</OnMatch>
</filter>
<!--日誌文件路徑,日誌文件名稱-->
<File>${LOG_HOME}/err_${LOG_PREFIX}.log</File>
<!-- 設置滾動策略,當天的日誌大小超過 ${MAX_FILE_SIZE} 文件大小時候,新的內容寫入新的文件, 默認10MB -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日誌文件路徑,新的 ERR 日誌文件名稱,“ i ” 是個變量 -->
<FileNamePattern>${LOG_DIR}/err_${LOG_PREFIX}%i.log</FileNamePattern>
<!-- 配置日誌的滾動時間 ,表示只保留最近 10 天的日誌-->
<MaxHistory>${MAX_HISTORY}</MaxHistory>
<!--當天的日誌大小超過 ${MAX_FILE_SIZE} 文件大小時候,新的內容寫入新的文件, 默認10MB-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 輸出的日誌內容格式化-->
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>${LOG_MSG}</Pattern>
</layout>
</appender>
<!-- additivity 設爲false,則logger內容不附加至root ,配置以配置包下的所有類的日誌的打印,級別是 ERROR-->
<logger name="org.springframework" level="ERROR" />
<logger name="org.apache.commons" level="ERROR" />
<logger name="org.apache.zookeeper" level="ERROR" />
<logger name="com.alibaba.dubbo.monitor" level="ERROR"/>
<logger name="com.alibaba.dubbo.remoting" level="ERROR" />
<!-- ${LOG_ROOT_LEVEL} 日誌級別 -->
<root level="${LOG_ROOT_LEVEL}">
<!-- 標識這個"${STDOUT}"將會添加到這個logger -->
<appender-ref ref="${STDOUT}"/>
<!-- FILE_ALL 日誌輸出添加到 logger -->
<appender-ref ref="FILE_ALL"/>
<!-- FILE_ERROR 日誌輸出添加到 logger -->
<appender-ref ref="FILE_ERROR"/>
</root>
</configuration>
配置文件 application.yml
:
logging:
file:
path: ./logs # 日誌文件路徑
日誌會每天新建一個文件夾,日文文件配置的每 50 M,一個文本文件,超過新寫入一個:
文件夾:20191130
文件夾內容:all_api-test-logback0.log
文件夾內容:all_api-test-logback1.log
文件夾內容:all_api-test-logback2.log
文件夾內容:err_api-test-logback0.log
多環境日誌輸出
根據不同環境(prod:生產環境,test:測試環境,dev:開發環境)來定義不同的日誌輸出,在 logback-spring.xml中使用 springProfile 節點來定義,方法如下:
文件名稱不是 logback.xml,想使用 spring 擴展 profile 支持,要以 logback-spring.xml
命名
<!-- 生產環境生效 -->
<springProfile name="prod">
<root level="error">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</springProfile>
<!-- 測試和開發環境日誌級別爲INFO/並且記錄日誌文件 -->
<springProfile name="dev,test">
<!-- 日誌輸出級別 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</springProfile>
然後跑測時,maven 命令加入參數 -P 命令即可指定相應的環境資源,比如: -Ptest,則會替換 test 環境下的參數值。
mvn clean install -DskipTests -Ptest
到此爲止終於介紹完集成 Logback 日誌框架了,平時使用的時候推薦用自定義 logback-spring.xml
來配置,代碼中使用日誌也很簡單,可以使用 lombok 效率插件配合 @Slf4j
註解快捷使用。
性能監控
而在測試的運維過程中,日誌系統又可以幫助我們記錄大部分的異常信息。通常很多測試框架會通過收集日誌信息來對接口測試狀態進行實時監控預警,比如慢SQL。所以我們選擇了一款強大的連接池Druid和小巧的工具 p6spy。
Druid
Druid 是一個關係型數據庫連接池,它是阿里巴巴的一個開源項目。Druid 支持所有 JDBC 兼容數據庫,包括了Oracle、MySQL、PostgreSQL、SQL Server、H2等。
Druid 在監控、可擴展性、穩定性和性能方面具有明顯的優勢。通過 Druid 提供的監控功能,可以實時觀察數據庫連接池和SQL查詢的工作情況。使用 Druid 連接池在一定程度上可以提高數據訪問效率。
首先需要引入依賴包:
<!-- 數據庫連接池druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
application.yml
啓用配置:
spring:
datasource:
dynamic:
primary: mysql # 設置默認的數據源或者數據源組,默認值即爲 master
strict: false # 設置嚴格模式,默認 false 不啓動. 啓動後在未匹配到指定數據源時候回拋出異常,不啓動會使用默認數據源.
druid:
filters: config,stat,slf4j # 配置監控統計攔截的filter,注意這個值和 druid 原生不一致,默認啓動了stat,wall
stat:
enabled: true
log-slow-sql: true # 開啓慢sql日誌
slow-sql-millis: 100 # 慢sql時間
max-wait: 3 # 最大連接等待時間
max-active: 5 # 最大連接池數量
min-idle: 2 # 最小連接池數量
validationQuery: SELECT 1
testWhileIdle: true # 申請連接的時候檢測,如果空閒時間大於 timeBetweenEvictionRunsMillis,執行validationQuery檢測連接是否有效
testOnBorrow: true # 申請連接時執行validationQuery檢測連接是否有效
testOnReturn: true # 歸還連接時執行validationQuery檢測連接是否有效
poolPreparedStatements: false
maxPoolPreparedStatementPerConnectionSize: 200
# druid: # 以下是全局默認值,可以全局更改
# initial-size:
# max-active:
# min-idle:
# max-wait:
# time-between-eviction-runs-millis:
# time-between-log-stats-millis:
# stat-sqlmax-size:
# min-evictable-idle-time-millis:
# max-evictable-idle-time-millis:
# test-while-idle:
# test-on-borrow:
# test-on-return:
# validation-query:
# validation-query-timeout:
# use-global-datasource-stat:
# async-init:
# clear-filters-enable:
# reset-stat-enable:
# not-full-timeout-retry-count:
# max-wait-thread-count:
# fail-fast:
# phyTimeout-millis:
# keep-alive:
# pool-prepared-statements:
# init-variants:
# init-global-variants:
# use-unfair-lock:
# kill-when-socket-read-timeout:
# connection-properties:
# max-pool-prepared-statement-per-connection-size:
# init-connection-sqls:
# share-prepared-statements:
# connection-errorretry-attempts:
# break-after-acquire-failure:
# filters: stat,wall
logging:
level:
com.baomidou: debug
org.springframework.jdbc.datasource.init: debug
此處只是簡單演示如何使用,詳細介紹可以參考官方資料。
P6Spy
p6spy 是一個開源項目,通常使用它來跟蹤數據庫操作,查看程序運行過程中執行的sql語句。
p6sy大部分人最常用的功能就是格式化你的sql語句。
# 如在使用 mybatis 的過程中,原生輸出的語句是帶?號的。在需要複製到其他地方執行看效果的時候很不方便。
select * from user where age>?
# 在使用了 p6sy 後,其會幫你格式化成真正的執行語句。
select * from user where age>6
引入依賴包:
<!--p6spy-->
<dependency>
<artifactId>p6spy</artifactId>
<groupId>p6spy</groupId>
<version>3.8.0</version>
</dependency>
啓用配置:
spring:
datasource:
dynamic:
p6spy: true # 默認false,建議線上關閉。
引入相關配置文件。
在 classPath 下創建 spy.properties
:
# 一個最簡單配置,定義slf4j日誌輸出。 更多參數請自行了解。
appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
編寫測試用例
在此一併解決之前某個同學提出如何解決測試用例多個參數的問題,即在測試用例表中存放json map 格式的參數。
多參數據構造
這裏還是演示一個參數,
{"Parameters":"latte"}
如果有多個參考,再添加一個鍵值對即可:
{"Parameters1":"latte1","Parameters2":"latte2"}
解析參數
即然參數是 json 格式,那麼我在取參數的時候需要解析。此處我們使用阿里開源的 fastjson 解析庫。
首先需要引包:
<!--引入 fastjson 序列化庫-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
編寫一個解析FastJson工具類,FastJsonUtils:
/***
* 解析爲字符串
*
* @param jsonString json字符串
* @param key 關鍵字
* @return 返回值
*/
public static String fromString(String jsonString, String key) {
try {
if (jsonString != null && jsonString.length() > 0) {
JSONObject jsonObject = JSONObject.parseObject(jsonString);
return jsonObject.getString(key);
} else {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
這時候我們的測試用例邏輯如下:
@Test(dataProvider = "testData",description = "測試demo")
public void testSelect(Map<String, String> data) throws InterruptedException {
// 參數取值
String parameters = FastJsonUtils.fromString(data.get("Parameters"),"Parameters");
// 封裝查詢條件
CoffeeExample example = new CoffeeExample();
//創建一個 Criteria,來拼裝查詢條件
example.createCriteria().andNameEqualTo(parameters);
// 查詢數據
List<Coffee> list = coffeeService.selectCoffeeFromDs(example);
// 循環打印
list.forEach(e -> log.info("selectByExample: {}", e));
// 篩選指定屬性
List<Money> moneys = list.stream().map(Coffee::getPrice).collect(Collectors.toList());
log.info( moneys.get(0).toString() );
// 斷言結果
Assert.assertEquals(data.get("expected"),moneys.get(0).toString());
}
注意這裏需要了解 mybatis Example條件查詢。
mybatis 的逆向工程中會生成實例及實例對應的 example,example 用於添加條件,相當where 後面的部分
xxxExample example = new xxxExample();
Criteria criteria = new Example().createCriteria();
criteria.andXxxEqualTo(value),表示添加 xxx 字段等於 value 條件。
執行 jdbcAPI-TestSuite.xml ,我們可以查看測試結果。
- | [20191210 22:19:59.328] | [DEBUG] | [DESKTOP-MLD0KTS] | [main] | [c.b.d.d.DynamicRoutingDataSource] | --> dynamic-datasource switch to the datasource named [h2]|
- | [20191210 22:19:59.338] | [INFO] | [DESKTOP-MLD0KTS] | [main] | [p6spy] | --> 2019-12-10 22:19:59|0|statement|connection 1|url |select ID, NAME, PRICE, CREATE_TIME, UPDATE_TIME from T_COFFEE WHERE ( NAME = ? )|select ID, NAME, PRICE, CREATE_TIME, UPDATE_TIME from T_COFFEE WHERE ( NAME = 'latte' )|
- | [20191210 22:19:59.356] | [INFO] | [DESKTOP-MLD0KTS] | [main] | [c.z.s.demo.TestMapperService] | --> selectByExample: Coffee [Hash = 1963590892, id=2, name=latte, price=CNY 25.00, createTime=Tue Dec 10 22:19:58 CST 2019, updateTime=Tue Dec 10 22:19:58 CST 2019]|
- | [20191210 22:19:59.356] | [INFO] | [DESKTOP-MLD0KTS] | [main] | [c.z.s.demo.TestMapperService] | --> CNY 25.00|
注意日誌中的 [p6spy]
行會打印程序執行的 sql 語句。
慢SQL測試
環境準備
- 操作系統:window/linux
- 數據庫: MySQL 5.7
數據準備
在 mysql_2
數據庫創建一個測試表:
CREATE TABLE emp
(empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '編號',
ename VARCHAR(20) NOT NULL DEFAULT "" COMMENT '名字',
job VARCHAR(9) NOT NULL DEFAULT "" COMMENT '工作',
mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '上級編號',
hiredate DATE NOT NULL COMMENT '入職時間',
sal DECIMAL(7,2) NOT NULL COMMENT '薪水',
comm DECIMAL(7,2) NOT NULL COMMENT '紅利',
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '部門編號'
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
構建一個存儲函數,這個存儲函數會返回一個長度爲參數 n 的隨機字符串
delimiter $$
create function rand_string(n INT)
returns varchar(255) #該函數會返回一個字符串
begin
declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
declare return_str varchar(255) default '';
declare i int default 0;
while i < n do
set return_str =concat(return_str,substring(chars_str,floor(1+rand()*52),1));
set i = i + 1;
end while;
return return_str;
end $$
delimiter ;
接下來我們再創建一個存儲函數,該存儲函數會返回一個隨機 int 值
delimiter $$
create function rand_num( )
returns int(5)
begin
declare i int default 0;
set i = floor(10+rand()*500);
return i;
end $$
delimiter ;
然後我們利用剛剛創建的兩個存儲函數創建一個存儲過程,該存儲過程包含一個參數,該參數表示插入數據表 emp 的數據條數
delimiter $$
create procedure insert_emp(in max_num int(10))
begin
declare i int default 0;
set autocommit = 0;
repeat
set i = i + 1;
insert into emp values (i ,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand_num());
until i = max_num
end repeat;
commit;
end $$
delimiter ;
我們調用創建的存儲過程,對 emp 表插入 1000w 條數據
call insert_emp(10000000);
統計表數據:
現在我們運行一個查詢時間超過 1s 的查詢語句:
慢查詢測試
在 TestDataMapper.xml
中新增:
<!-- 自定義SQL語句2 -->
<select id="selectBySlowsql" parameterType="String" resultType="java.util.LinkedHashMap">
${value};
</select>
編輯 TestDataMapper 新增 Dao 接口:
// 自定義sql查詢2
List<LinkedHashMap<String, Object>> selectBySlowsql(String sql);
編輯 TestDataService,新建 Service 接口:
// 自定義查詢2
List<LinkedHashMap<String, Object>> selectBySlowsql(String sql);
編輯 TestDataServiceImpl類,實現 Service 接口,並指定數據源:
@DS("mysql_2")
@Override
public List<LinkedHashMap<String, Object>> selectBySlowsql(String sql) {
return testDataMapper.selectBySlowsql(sql);
}
編寫測試方法:
@Test
public void testTestData() {
String sqlString = "SELECT * FROM emp WHERE empno = 403345;";
//調用
List<LinkedHashMap<String, Object>> names = testDataService.selectBySlowsql(sqlString);
names.forEach(name -> log.info("selectBySlowsql: {}", name));
執行測試如下:
- | [20191210 22:19:59.360] | [DEBUG] | [DESKTOP-MLD0KTS] | [main] | [c.b.d.d.DynamicRoutingDataSource] | --> dynamic-datasource switch to the datasource named [mysql_2]|
- | [20191210 22:20:05.058] | [ERROR] | [DESKTOP-MLD0KTS] | [main] | [c.a.druid.filter.stat.StatFilter] | --> slow sql 5684 millis. SELECT * FROM emp WHERE empno = 403345;;[]|
- | [20191210 22:20:05.059] | [INFO] | [DESKTOP-MLD0KTS] | [main] | [p6spy] | --> 2019-12-10 22:20:05|5685|statement|connection 2|url |SELECT * FROM emp WHERE empno = 403345;;|SELECT * FROM emp WHERE empno = 403345;;|
- | [20191210 22:20:05.062] | [INFO] | [DESKTOP-MLD0KTS] | [main] | [c.z.s.demo.TestMapperService] | --> selectBySlowsql: {empno=403345, ename=RbJamf, job=SALESMAN, mgr=1, hiredate=2018-09-13, sal=2000.00, comm=400.00, deptno=428}|
注意 [ERROR]
行已經打印出慢sql記錄,執行時間:5685毫秒
slow sql 5684 millis. SELECT * FROM emp WHERE empno = 403345;;[]|
全部代碼骨架結構
├─logs
│ └─spring-boot-logback # 日誌文件
│ all_api-test-logback.log # 所有日誌
│ err_api-test-logback.log # 錯誤日誌
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─zuozewei
│ │ │ └─springbootdatadrivendemo
│ │ │ │ SpringbootDataDrivenDemoApplication.java # 啓動類
│ │ │ │
│ │ │ ├─db
│ │ │ │ ├─auto # 存放MyBatis Generator生成器生成的數據層代碼,可以隨時刪除再生成
│ │ │ │ │ ├─mapper # DAO 接口
│ │ │ │ │ └─model # Entity 實體
│ │ │ │ └─manual # 存放自定義的數據層代碼,包括對MyBatis Generator自動生成代碼的擴展
│ │ │ │ ├─mapper # DAO 接口
│ │ │ │ └─model # Entity 實體
│ │ │ ├─handler # 數據轉換
│ │ │ └─service # 業務邏輯
│ │ │ └─impl # 實現類
│ │ │ └─utils # 工具類
│ │ │
│ │ └─resources
│ │ │ application.yml # 全局配置文件
│ │ │ generatorConfig.xml # Mybatis Generator 配置文件
│ │ │ logback-spring.xml # logback 配置文件
│ │ │ spy.properties # P6Spy 配置文件
│ │ │
│ │ ├─db
│ │ ├─mapper
│ │ │ └─com
│ │ │ └─zuozewei
│ │ │ └─springbootdatadrivendemo
│ │ │ └─db
│ │ │ ├─auto # 存放MyBatis Generator生成器生成的數據層代碼,可以隨時刪除再生成
│ │ │ │ └─mapper # 數據庫 Mapping 文件
│ │ │ │
│ │ │ └─manual # 存放自定義的數據層代碼,包括對MyBatis Generator自動生成代碼的擴展
│ │ │ └─mapper # 數據庫 Mapping 文件
│ │ └─testng
│ │ │ APICollection-TestSuite.xml # 所用測試用例集
│ │ └─jdbcbapi
│ │ jdbcAPI-TestSuite.xml # 某API測試用例集
│ │
│ └─test
│ └─java
│ └─com
│ └─zuozewei
│ └─springbootdatadrivendemo
│ └─demo # 接口測試用例
├─pom.xml
小結
在今天這篇文章中,主要和大家分享了實現日誌管理和性能監控的過程,另外也回覆之前某同學提出的用例多參數的問題。在實現過程中,你最需要關注的幾部分內容是:
- 基於
Druid
和P6spy
跟蹤sql語句和打印慢sql; - 使用
logback
搭建日誌框架; - 實現用例 json 多參數取值。
希望對你能有所啓發。
框架源碼:
https://github.com/zuozewei/Java-API-Test-Examples/tree/master/springboot-data-driven-framework-demo