讲解TestNG+MySQL+MyBatis+ExtentReports实现对测试用例数据的读取,下面放出所有配置文件的目录方便下文理解。

1.配置mysql数据库

在这里,拿logincase表举例,后面也拿login做讲解。

2.配置pom文件
首先在pom文件中,配置httpclient、mybatis、mysql、extentreports、testng的各种依赖。

<?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>com.course.code</groupId><artifactId>userInfoTest</artifactId><version>1.0-SNAPSHOT</version><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>6</source><target>6</target></configuration></plugin></plugins></build><dependencies><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.json</groupId><artifactId>json</artifactId><version>20170516</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.4</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>6.0.5</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.16</version></dependency><dependency><groupId>com.relevantcodes</groupId><artifactId>extentreports</artifactId><version>2.41.1</version></dependency><dependency><groupId>com.vimalselvam</groupId><artifactId>testng-extentsreport</artifactId><version>1.3.1</version></dependency><dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>6.11</version></dependency><dependency><groupId>com.aventstack</groupId><artifactId>extentreports</artifactId><version>3.0.6</version></dependency></dependencies>

3.配置application.properties文件
resource目录下配置application.properties文件,用以存储测试地址。

test.url=http://localhost:9529#登录接口
login.uri=/v1/login#更新用户信息
updateUserInfo.uri=/v1/updateUserInfo#获取用户列表
getUserList.uri=/v1/getUserList#获取用户信息
getUserInfo.uri=/v1/getUserInfo#添加用户接口
addUser.uri=/v1/addUser

4.配置databaseConfig.xml文件
resource目录下配置databaseConfig.xml文件,用以连接数据库。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- 注册对象的空间命名 --><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 加载数据驱动 --><property name="driver" value="com.mysql.jdbc.Driver"/><!-- 数据库连接地址 --><property name="url" value="jdbc:mysql://localhost:3306/myBatisTest"/><!-- 数据库用户、密码 --><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><!-- 注册映射文件:java对象与数据库之间的xml文件路径 --><mappers><mapper resource="mapper/SQLMapper.xml"/></mappers>
</configuration>

5.配置testng.xml文件
resource目录下配置testng.xml文件,用以执行所有testng的测试套件。

<?xml version="1.0" encoding="UTF-8" ?>
<suite name="用户管理系统测试套件"><test name="用户管理系统测试用例"><classes><class name="com.course.cases.loginTest"><methods><include name="loginTrue"/><include name="loginFalse"/></methods></class><class name = "com.course.cases.AddUserTest"><methods><include name="addUser"/></methods></class><class name = "com.course.cases.GetUserInfoTest"><methods><include name="getUserInfo"/></methods></class><class name = "com.course.cases.GetUserListTest"><methods><include name="getUserList"/></methods></class><class name = "com.course.cases.UpdateUserInfoTest"><methods><include name="updateUserInfo"/><include name="deleteUser"/></methods></class></classes></test><listeners><listener class-name="com.course.config.ExtentTestNGIReporterListener"></listener></listeners>
</suite>

6.配置SQLMapper.xml文件
resources/mapper目录下,配置SQLMapper.xml文件,用户存储所有case的sql语句。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.course.model"><!--获取登录接口case--><select id="loginCase" parameterType="Integer" resultType="com.course.model.LoginCase">select * from loginCasewhere id=#{id};</select><!--添加用户接口case--><select id="addUserCase" parameterType="Integer" resultType="com.course.model.AddUserCase">select * from addUserCase where id=#{id};</select><!--获取用户信息case--><select id="getUserInfoCase" parameterType="Integer" resultType="com.course.model.GetUserInfoCase">select * from getUserInfoCase where id=#{id};</select><!--获取用户列表case--><select id="getUserListCase" parameterType="Integer" resultType="com.course.model.GetUserListCase">select * from getUserListCase where id = #{id};</select><!--更新/删除用户case--><select id="updateUserInfoCase" parameterType="Integer" resultType="com.course.model.UpdateUserInfoCase">select * from updateUserInfoCase where id = #{id};</select>
</mapper>

7.配置model文件
com.course.model目录下,配置各个接口的数据配置文件,和一个InterfaceName枚举。

在这里,同样拿LoginCase里的数据举例,其他case的格式一样。在这里参照mysql里配置的字段一一进行声明。

@Data
public class LoginCase {private int id;private String userName;private String password;private String expected;
}

InterfaceName配置如下

public enum InterfaceName {GETUSERLIST,LOGIN,UPDATEUSERINFO,GETUSERINFO,ADDUSER
}

8.配置config文件
com.course.config目录下,新建ExtentTestNGIReporterListener文件和TestConfig文件。
ExtentTestNGIReporterListener里是ExtentReport的测试报告配置文件,固定代码可以直接拷过去使用。

public class ExtentTestNGIReporterListener implements IReporter {//生成的路径以及文件名private static final String OUTPUT_FOLDER = "test-output/";private static final String FILE_NAME = "index.html";private ExtentReports extent;@Overridepublic void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {init();boolean createSuiteNode = false;if(suites.size()>1){createSuiteNode=true;}for (ISuite suite : suites) {Map<String, ISuiteResult> result = suite.getResults();//如果suite里面没有任何用例,直接跳过,不在报告里生成if(result.size()==0){continue;}//统计suite下的成功、失败、跳过的总用例数int suiteFailSize=0;int suitePassSize=0;int suiteSkipSize=0;ExtentTest suiteTest=null;//存在多个suite的情况下,在报告中将同一个一个suite的测试结果归为一类,创建一级节点。if(createSuiteNode){suiteTest = extent.createTest(suite.getName()).assignCategory(suite.getName());}boolean createSuiteResultNode = false;if(result.size()>1){createSuiteResultNode=true;}for (ISuiteResult r : result.values()) {ExtentTest resultNode;ITestContext context = r.getTestContext();if(createSuiteResultNode){//没有创建suite的情况下,将在SuiteResult的创建为一级节点,否则创建为suite的一个子节点。if( null == suiteTest){resultNode = extent.createTest(r.getTestContext().getName());}else{resultNode = suiteTest.createNode(r.getTestContext().getName());}}else{resultNode = suiteTest;}if(resultNode != null){resultNode.getModel().setName(suite.getName()+" : "+r.getTestContext().getName());if(resultNode.getModel().hasCategory()){resultNode.assignCategory(r.getTestContext().getName());}else{resultNode.assignCategory(suite.getName(),r.getTestContext().getName());}resultNode.getModel().setStartTime(r.getTestContext().getStartDate());resultNode.getModel().setEndTime(r.getTestContext().getEndDate());//统计SuiteResult下的数据int passSize = r.getTestContext().getPassedTests().size();int failSize = r.getTestContext().getFailedTests().size();int skipSize = r.getTestContext().getSkippedTests().size();suitePassSize += passSize;suiteFailSize += failSize;suiteSkipSize += skipSize;if(failSize>0){resultNode.getModel().setStatus(Status.FAIL);}resultNode.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",passSize,failSize,skipSize));}buildTestNodes(resultNode,context.getFailedTests(), Status.FAIL);buildTestNodes(resultNode,context.getSkippedTests(), Status.SKIP);buildTestNodes(resultNode,context.getPassedTests(), Status.PASS);}if(suiteTest!= null){suiteTest.getModel().setDescription(String.format("Pass: %s ; Fail: %s ; Skip: %s ;",suitePassSize,suiteFailSize,suiteSkipSize));if(suiteFailSize>0){suiteTest.getModel().setStatus(Status.FAIL);}}}
//        for (String s : Reporter.getOutput()) {//            extent.setTestRunnerOutput(s);
//        }extent.flush();}private void init() {//文件夹不存在的话进行创建File reportDir= new File(OUTPUT_FOLDER);if(!reportDir.exists()&& !reportDir .isDirectory()){reportDir.mkdir();}ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(OUTPUT_FOLDER + FILE_NAME);// 设置静态文件的DNS//怎么样解决cdn.rawgit.com访问不了的情况htmlReporter.config().setResourceCDN(ResourceCDN.EXTENTREPORTS);htmlReporter.config().setDocumentTitle("api自动化测试报告");htmlReporter.config().setReportName("api自动化测试报告");htmlReporter.config().setChartVisibilityOnOpen(true);htmlReporter.config().setTestViewChartLocation(ChartLocation.TOP);htmlReporter.config().setTheme(Theme.STANDARD);htmlReporter.config().setCSS(".node.level-1  ul{ display:none;} .node.level-1.active ul{display:block;}");extent = new ExtentReports();extent.attachReporter(htmlReporter);extent.setReportUsesManualConfiguration(true);}private void buildTestNodes(ExtentTest extenttest, IResultMap tests, Status status) {//存在父节点时,获取父节点的标签String[] categories=new String[0];if(extenttest != null ){List<TestAttribute> categoryList = extenttest.getModel().getCategoryContext().getAll();categories = new String[categoryList.size()];for(int index=0;index<categoryList.size();index++){categories[index] = categoryList.get(index).getName();}}ExtentTest test;if (tests.size() > 0) {//调整用例排序,按时间排序Set<ITestResult> treeSet = new TreeSet<ITestResult>(new Comparator<ITestResult>() {@Overridepublic int compare(ITestResult o1, ITestResult o2) {return o1.getStartMillis()<o2.getStartMillis()?-1:1;}});treeSet.addAll(tests.getAllResults());for (ITestResult result : treeSet) {Object[] parameters = result.getParameters();String name="";//如果有参数,则使用参数的toString组合代替报告中的namefor(Object param:parameters){name+=param.toString();}if(name.length()>0){if(name.length()>50){name= name.substring(0,49)+"...";}}else{name = result.getMethod().getMethodName();}if(extenttest==null){test = extent.createTest(name);}else{//作为子节点进行创建时,设置同父节点的标签一致,便于报告检索。test = extenttest.createNode(name).assignCategory(categories);}//test.getModel().setDescription(description.toString());//test = extent.createTest(result.getMethod().getMethodName());for (String group : result.getMethod().getGroups())test.assignCategory(group);List<String> outputList = Reporter.getOutput(result);for(String output:outputList){//将用例的log输出报告中test.debug(output);}if (result.getThrowable() != null) {test.log(status, result.getThrowable());}else {test.log(status, "Test " + status.toString().toLowerCase() + "ed");}test.getModel().setStartTime(getTime(result.getStartMillis()));test.getModel().setEndTime(getTime(result.getEndMillis()));}}}private Date getTime(long millis) {Calendar calendar = Calendar.getInstance();calendar.setTimeInMillis(millis);return calendar.getTime();}
}

TestConfig内声明各个case的url和之后要用的一些变量。

public class TestConfig {public static String loginUrl;public static String updateUserInfoUrl;public static String getUserListUrl;public static String getUserInfoUrl;public static String addUserUrl;public static DefaultHttpClient defaultHttpClient;public static CookieStore store;
}

9.配置utils文件
com.course.utils目录下配置ConfigFile文件和DatabaseUtil文件。

ConfigFile内对各个case的url进行赋值

public class ConfigFile {public static ResourceBundle bundle = ResourceBundle.getBundle("application",Locale.CHINA);public static String getUrl(InterfaceName name){String address = bundle.getString("test.url");String uri = "";//最终测试地址String testUrl;if (name == InterfaceName.GETUSERLIST){uri = bundle.getString("getUserList.uri");}if (name == InterfaceName.LOGIN){uri = bundle.getString("login.uri");}if (name == InterfaceName.UPDATEUSERINFO){uri = bundle.getString("updateUserInfo.uri");}if (name == InterfaceName.GETUSERINFO){uri = bundle.getString("getUserInfo.uri");}if (name == InterfaceName.ADDUSER){uri = bundle.getString("addUser.uri");}testUrl = address + uri;return testUrl;}}

DatabaseUtil内配置一个getSqlsession方法,作用是执行配置文件中的sql语句,用以之后每个case可以直接调用而不用重复的写这一部分代码。

public class DatabaseUtil {public static SqlSession getSqlsession() throws IOException {//获取配置资源文件Reader reader = Resources.getResourceAsReader("databaseConfig.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);//sqlSession就是能够执行配置文件中的sql语句SqlSession sqlSession=factory.openSession();return sqlSession;}
}

10.配置cases文件
com.course.cases目录下配置所有case类
在这里也只拿loginTest进行举例

public class loginTest {@BeforeTest(groups="loginTrue",description = "测试准备工作,获取httpClient对象")public void beforeTest(){TestConfig.getUserInfoUrl = ConfigFile.getUrl(InterfaceName.GETUSERINFO);TestConfig.getUserListUrl = ConfigFile.getUrl(InterfaceName.GETUSERLIST);TestConfig.addUserUrl = ConfigFile.getUrl(InterfaceName.ADDUSER);TestConfig.loginUrl = ConfigFile.getUrl(InterfaceName.LOGIN);TestConfig.updateUserInfoUrl = ConfigFile.getUrl(InterfaceName.UPDATEUSERINFO);TestConfig.defaultHttpClient = new DefaultHttpClient();}@Test(groups = "loginTrue",description = "用户登录接口测试")public void loginTrue() throws IOException {SqlSession session = DatabaseUtil.getSqlsession();LoginCase loginCase = session.selectOne("loginCase",1);System.out.println(loginCase.toString());System.out.println(TestConfig.loginUrl);}@Test(description = "用户登录失败接口测试")public void loginFalse() throws IOException {SqlSession session = DatabaseUtil.getSqlsession();LoginCase loginCase = session.selectOne("loginCase",2);System.out.println(loginCase.toString());System.out.println(TestConfig.loginUrl);}
}

到这里,一套完整的从mysql读取测试用例数据到存储在java工程内的配置就写完了
我们可以执行一下testng.xml文件,可以看到所有case都执行成功,并且在控制台上打印出了所有数据信息以及每个case的url。

最后查看一下test-output目录下的index.xml文件,用浏览器打开可以看到ExtentReport的结果也生成成功。

第一:MySQL+MyBatis实现对测试用例数据的读取(接口自动化落地)相关推荐

  1. 大数据服务平台---接口自动化

    大数据服务平台接口自动化-实践 业务背景: 某大数据风险智能服务平台,海量的风险.舆情.情报.文书等工商信息.除了用户pc端.app端的应用,还有细分后台管理功能. 接口自动化背景分析: 1. 数据服 ...

  2. mysql xa 序列化_MYSQL 的数据序列化Api接口详情

    MYSQL 的数据序列化Api接口详情 发布时间:2020-04-29 17:02:59 来源:亿速云 阅读:158 作者:三月 本文主要给大家介绍MYSQL 的数据序列化Api接口详情,文章内容都是 ...

  3. 大智慧股票本地数据l2读取接口如何建立数据库?

    UNIX:基于文件的协作小工具 为了追求简单性,我们可以尝试尽可能多的删除层和软件,并减少需要交付的自定义代码的数量.这将有助于降低运营费用和减少工作和维护的总量. 在考虑这一点时,我们可以重用经典的 ...

  4. Python语言+pytest框架+allure报告+log日志+yaml文件+mysql断言实现接口自动化框架

    目录 前言 实现功能 目录结构 依赖库 安装教程 接口文档 如何创建用例 创建用例步骤 用例中相关字段的介绍 如何发送get请求 如何发送post请求 如何测试上传文件接口 上传文件接口,即需要上传文 ...

  5. Yaml版接口自动化详细讲解(Python + pytest + allure + log + yaml + mysql + redis + 钉钉通知 + Jenkins)

    目录 框架介绍 框架结构 框架功能讲解 common  # 配置 config.yaml  # 公共配置 setting.py  # 环境路径存放区域 data  # 测试用例数据 Files  #  ...

  6. 自动化测试用例设计原则(接口自动化用例设计的基本原则)

    自动化测试用例设计原则: 1.一个脚本是一个完整的场景,从用户登陆操作到用户退出系统关闭浏览器. 2.一个脚本脚本只验证一个功能点,不要试图用户登陆系统后把所有的功能都进行验证再退出系统 3.尽量只做 ...

  7. springboot+mybatis+sqlserver导出数据库数据并实现下载到excel

    springboot+mybatis+sqlserver导出数据库数据并实现下载到excel 1.准备工作 1.1 下载一个springboot框架demo 1.2 配置maven 1.3 引入需要的 ...

  8. Java Persistence with MyBatis 3(中文版) 第一章 MyBatis入门

    本章将涵盖以下话题: ž  MyBatis是什么? ž  为什么选择MyBatis? ž  MyBatis安装配置 ž  域模型样例 1.1 MyBatis是什么 MyBatis是一个简化和实现了Ja ...

  9. MySQL+Mybatis

    目录 一.事务 1.概念 2.事务的基本特性(ACID) 3.事务中并发一致性的问题 4.事务的隔离级别 二.MySQL的锁 1.按锁的粒度分类: 2.按锁的类型分类: 3.InNoDB中行锁定的方式 ...

最新文章

  1. 计算机网络管理的常用命令,网络管理常用命令图文详解.pdf
  2. SQL学习笔记-嵌套查询
  3. Zend Framework中,执行自定义sql语句
  4. 基于结构化数据的文本生成:非严格对齐生成任务及动态轻量的GCN生成模型
  5. postgresql操作
  6. python服务器查看文件更改记录,Python记录到同一文件,不同用户
  7. 全球视频监控设备市场规模分析
  8. 兼容所有浏览器的省略号--纯CSS策略
  9. 复用类库内部已有功能
  10. SQLServer------基本操作
  11. 采用Eclipse为IDE,设计一个Java程序,实现根据指定年份、月份计算该月天数的功能,即程序输入为年、月,输出为该月的天数。
  12. 查看ip地址 通过域名
  13. 浅谈移动端图片压缩(iOS Android)
  14. 设计模式之原型模式(C语言)
  15. Ceph-ansible 安装 ceph (rbd + rgw)
  16. 国家的mysql表_中国省份数据库+世界国家名数据库
  17. 2020 年移动开发趋势
  18. QueryWrapper方法
  19. 前后端分离跨服务器文件上传,SpringBoot+Vue.js实现前后端分离的文件上传功能
  20. 台式计算机机箱的作用,如何选购台式电脑机箱?小白装机选购电脑机箱知识指南...

热门文章

  1. 45度地图遮挡问题解决方案(cocos2d-x)
  2. Linux与Windows关于标准输入中涉及EOF的处理方式
  3. cocos creator基础-(十三)cc.Loader使用
  4. Asp.Net IHttpHandler介绍
  5. java 过滤器filter使用案例
  6. hdu 5710 Digit-Sum (构造题)
  7. Java 导出Excel的各种尝试
  8. 五通信算法:五种编码增益比较matlab模拟
  9. SpringMVC Java config freemarker
  10. 对路径XXX的访问被拒绝(文件操作权限)的解决方法