基于 Junit 的接口自动化测试框架实现!

基于 Junit 的接口自动化测试框架实现

分层的自动化测试

5~10 年前,我们接触的自动化测试更关注的是 UI 层的自动化测试,Mercury 的 WinRunner/QTP 是那个时代商业性自动化测试产品的典型代表,在那个时代大家单纯想的都是能用一个自动化操作的工具替代人力的点击,商业化或是私有化框架大行其道。

而分层的自动化测试倡导产品的不同阶段(层次)都需要自动化测试。在《Google 软件测试之道》中,在 Google 70% 的投入为单元测试(小型测试),20% 为接口 / 集成测试(中型测试),10% 为 UI 层的自动化测试(大型测试),也就是大家熟悉的金字塔模型,越往上自动化实现难度越大,投入产生的收益也越低(需要强调的是,UI 层的自动化测试作为最接近用户操作的测试,仍然有其存在的意义和场景)。

接口测试的意义

接口测试是验证两个或多个模块应用之间的交互(通常是采用接口的方式),测试的重点是要检查数据的交换,传递和控制管理过程,还包括处理的次数。

接口测试的核心战略在于:以保证系统的正确和稳定为核心,以持续集成为手段,提高测试效率,提升用户体验,降低产品研发成本。

接口测试要为代码的编写保驾护航,增强开发人员和测试人员的自信,让隐含的 BUG 提前暴露出来,要让开发人员在第一时间修复 BUG,要让业务测试人员在测试的时候更加顺手,最大限度得减少底层 BUG 的出现数量,要让产品研发的流程更加敏捷,要缩短产品的研发周期,最后在产品上线以后,要让用户用得更加顺畅,要让用户感觉产品服务零缺陷。

不同于单元测试,接口测试本质上还是一种黑盒的测试,所以非常适合专职测试工程师去参与和覆盖。

现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:110685036【暗号:csdn999】

接口测试框架选型

  1. 目前接口测试框架的选型,最常见的方法是采用 JMeter、soapUI、postman、robotframework 等 UI 化的接口测试框架来做。

好处是业务测试人员可以不用或很少写测试代码,入门门槛低,前几年有很多公司都曾经开发过类似的测试框架,有前端有后端,专职的测试开发人员维护,业务测试人员只需要知道怎么操作而不需要参与具体 coding。
这种方法看起来非常高大上,但实际的问题是执行过程中主要的工作变成了测试框架的维护,非常依赖专职测试开发人员的设计和开发能力,每增加一种新的接口协议(比如 Dubbo、Hessian 或者内部自定义的协议)就需要在框架上增加支持;更致命的是一旦核心测试开发人员出现流动,就很容易造成整个接口测试体系的崩塌;另外对业务测试人员的技能成长也并不公平,个人已面试过太多只会使用某大公司 XXX 测试框架却完全不了解具体实现方式的工程师。

《Google 软件测试之道》中早已有过预言,保密和私有化的基础测试设施并不能获得想象中的好处,这种方式意味着昂贵和迟缓,即使在公司内部的不同项目之间也很难做到复用。未来的测试基础设施必然是建立在共享代码和开源框架的基础上,测试开发人员需要更多的利用开源项目并为之贡献。最近重读了一次这本几乎改变软件测试行业的书籍,发现里面的预言都是如此准确,当然也可以认为国内整个行业都正参照 Google 的方式在进行演变。

  1. 使用 Junit、Testng 等 Java 接口框架,直接编写测试代码去测试,同时对一些重复性的工作抽象建立基础库或方法。

有点类似于单元测试,这种方法扩展性好实现灵活,作为程序员可以用代码实现灵活的场景组织和功能,只要稍微二次开发一下,但需要测试工程师有一定的编码基础。 

这种方式在前几年实施的难度还是比较大,因为在市场上要找到懂 Java 代码的测试工程师都寥寥无几,但在对测试工程师开发能力要求越来越多的今天实施难度已没有想象中困难,Java/Python 等语言的编码能力也已成为我们团队招聘时的基本要求。

另外提下,这里使用 Java 而不用其他语言的原因,主要是团队的技术储备 Java 是强项 , 拥有丰富的开源测试库,而且一般互联网公司的产品基本都是采用 Java 框架进行开发,和开发团队技术栈保持一致非常有必要性。

GTest 接口测试框架

有很多公司做了各种不同的接口框架,都是基于自己公司的业务基础设计开发。我们基于自己的业务特点也封装了自己的接口测试框架 gtest-framework,在开发人员的单元测试中也正逐渐使用。

gtest-framework 要做的事情:

  1. 前置数据准备和自动清理。
  2. 常见接口协议的实现和封装。
  3. 依赖注入配置方式的支持。
  4. 如文件、图片、xml、字符等各类通用处理方法的集成。
  5. 断言方式的扩展等。

接口测试关键实践

1. 数据准备

接口测试的数据准备,一般是指数据库的数据准备,有时候还包括文件和缓存的数据准备。具体实现可以从下面几个方面去考虑

(1)硬编码的方式准备测试数据,在写测试代码的时候,使用到什么数据就插入什么数据。为了避免数据重复,很多人会习惯于使用随机字符或随机数(这种方法可能造成测试用例不稳定,尽量避免)。

(2)可以直接通过调用其他 API 的方式准备测试数据,这种情况在测试最上层服务的时候比较有用,比如测试购买商品,就需要准备要购买的商品数据,购买商品的用户数据,这个时候,可以直接调用生成商品的 API 和生成用户的 API 直接生成测试数据。此方法实现简单,但前提是需要具备相应的 API 并且此 API 功能正确。

(3)使用 Excel 或 XML 准备测试数据,这种准备测试数据的方式,主要针对对象数据的准备,比如可以将一条商品数据对应 Excel 中的一条数据,因为一般开发都会使用 pojo 映射,而在准备测试数据的时候,这些 pojo 对象属性的设置往往是重复和大工作量的,用 Excel 或 XML 方式准备,则可以减少在代码当中重复去准备这些数据。

一般我们使用的是 2/3 两种方式,其中 3 这种方式主要利用 Dbunit、Spring-test、Unitils 等测试框架的特性经二次开发增加自定义注解,很轻松的导入 Excel 或 XML 格式的文件并在测试完成后对数据进行自动回滚。

/** 
* @ClassName: TestJdbcDataSet 
* @Description: 采用自定义 TestDataSet 注解方式准备测试数据,推荐。
* @author Cay.Jiang   
* @date 2017 年 7 月 10 日 上午 9:10:29 
*  
*/
public class TestJdbcDataSet extends BaseCase{
    Map<String, Object> args = new HashMap<String, Object>();
    @Test
    @TestDataSet(locations={"/tmp/domaininfo.xls"},dsNames={"mysqlDataSource"})
    public void test01_mysql(){
        args.put("selfdomain", "baidupc2");
        List<Map<String, Object>> result=JdbcUtil.queryData(mysqlJdbcTemplate, "domaininfo", args);
        System.out.println(result);
        assertEquals(" 合作商接入名称 ",result.get(0).get("remark"));
    }
}

上面代码中的 /tmp/domaininfo.xls 参见:domaininfo.xls ,其中 Excel 格式以 Sheet 名为表名,第一行定义了字段名称,其余行为对应的数据。

多数据集:
@TestDataDataSet(locations={"Data1.xls","Data2.xls"},dsNames={"dsNameA","dsNameB"}),Data1.xls 的数据会插入 dsNameA 所指的数据库中,Data2.xls 的数据会插入 dsNameB 所指的数据库中

2. 断言

常见的断言方式有 JUnit 自带的 Assert 和 Hamcrest。JUnit 自带的断言方法功能十分有限只能满足最基本的需求。Hamcrest 相对来讲功能丰富一些,但是该库已经多年不更新。而且 Hamcrest 和 JUnit 自带的断言方法一样,有个致命的缺点,就是当一个 case 中有多个断言时,如果其中一个断言失败,那么在它之后的断言都不会执行。这里向大家推荐一款新的断言神器 AssertJ。

AseertJ: 号称流式断言。什么是流式,常见的断言器一条断言语句只能对实际值断言一个校验点,而 AseertJ 支持一条断言语句对实际值同时断言多个校验点,这样使得断言的语句更加简洁适合阅读。AseertJ 还支持一次性执行所有断言,然后收集所有失败的断言一起反馈。当然除此之外 AseertJ 还有很多其他特性,可以参考官方文档慢慢挖掘。下面将举例说明一下 AseertJ 的优势:

public class TestCase extends BaseCase{
    UserProfileBO user = new UserProfileBO();
    @Before
    public void init(){
        user.setAddress(" 杭州 ");
        user.setMobile("1386800000");
        user.setUserName(" 测试账号 ");
    }

    /*
     * JUnit 内置的断言
     * 
     * 1、其中一个断言失败后,后面所有断言将不会执行。
     * 2、支持的断言方法较少
     * 
     */
    @Test
    public void testAssertJUnit(){

        Assert.assertEquals(" 地址 ",user.getAddress()," 宁波 ");
        Assert.assertEquals(" 手机 ",user.getMobile(),"13868000000");
        Assert.assertEquals(" 手机 ",user.getUserName()," 测试 ");

        Assert.assertNotNull(user.getMobile());
        Assert.assertTrue(user.getMobile().startsWith("138"));
        Assert.assertTrue(user.getMobile().length() == 11);

    }

    /*
     * Hamcres 断言
     * 
     * 1、其中一个断言失败后,后面所有断言将不会执行。
     * 2、支持的断言方法丰富,但是已经多年不更新。
     * 
     */
    @Test 
    public void testHamcrestMatchers() {  

        MatcherAssert.assertThat(user.getAddress(), equalTo(" 宁波 "));  
        MatcherAssert.assertThat(user.getMobile(), equalTo("13868000000"));  
        MatcherAssert.assertThat(user.getUserName(), equalTo(" 测试 "));  

        MatcherAssert.assertThat(user.getMobile(), allOf(is(nullValue()),startsWith("136")));  
    }

    /*
     * AssertJ 断言
     * 
     * 1、支持所有断言执行后,失败断言统一反馈。
     * 2、支持的断言方法丰富。
     * 3、支持流式断言,方便阅读。
     * 
     */
    @Test
    public void testAssertJ(){

        // 断言集合,执行所有断言后,失败断言统一反馈。
        SoftAssertions.assertSoftly(softly -> {
            softly.assertThat(user.getAddress().equals(" 宁波 "));
            softly.assertThat(user.getMobile().equals("13868000000"));
            softly.assertThat(user.getUserName().equals(" 测试 "));
        });

        // 流式断言
        Assertions.assertThat(user.getMobile())
            .isNotNull()
            .startsWith("136")
            .hasSize(11);

    }
}

3.jenkins 集成接口测试

(1)设置测试代码的仓库地址及身份信息

(2)设置 maven 运行参数

希望执行部分接口用例,可以通过-Dtest=XXX(测试类名) 的方式执行指定的 case,多个类名用逗号 “,” 隔开

(3)设置 Job 执行机制,下图表示每天定时执行

4.pipeline 参数注入

前面写 pipeline 的时候提过,我们的接口测试代码是需要支持外部参数注入的,比如测试的服务地址,不同的分支代码可能部署在不同测试服务器上,需要在 pipeline 中通过参数化的方式驱动对不同的服务器进行接口测试。

这里我们可以使用 maven 的-D(Properties 属性)来实现,举例如下:

(1)dubbo 使用 properties 配置文件,但具体参数使用 ${key}占位符方式打包替换

(2)maven 的 pom 文件中指定对应配置文件中的参数值 (此处指定的参数值会被通过 maven -D 传递过来的参数值覆盖)

此处注意:还需要启动 resources 的 filter 过滤器

(3) 使用 maven 命令行设置属性值

并对该值进行参数化支持 pipeline 传参

5.Pipeline 代码实现

      stage(' 接口自动化测试 ') {
            steps{
                echo "starting interfaceTest......"
                script {
                 // 为确保 jetty 启动完成,加了一个判断,确保 jetty 服务器启动可以访问后再执行接口层测试。
                 timeout(5) {
                     waitUntil {
                        try {
                            // 确保 jetty 服务的端口启动成功
                            sh "nc -z ${serverIP} ${jettyPort}"
                            //sh "wget -q http://${serverIP}:${jettyPort} -O /dev/null"
                            return true
                        } catch (exception) {
                            return false
                            }
                        }
                    }
                // 将参数 IP 和 Port 传入到接口测试的 job,需要确保接口测试的 job 参数可注入
                 build job: ITEST_JOBNAME, parameters: [string(name: "dubbourl", value: "${serverIP}:${params.dubboPort}")]
                }
            }
        }

测试代码规范 (仅供参考)

  1. 测试项目命名规范

接口测试:
一般需要独立测试项目,测试项目的命名规则为:“test-“+ 被测试的项目名,如 test-kano。
单元测试:
不需要重建独立测试项目,和开发代码放在同一项目即可。

  1. 测试目录定义规范

测试代码统一放在测试项目的 “src/test/java” 下。
测试配置文件统一放置在 “src/test/resources” 下。

  1. 包名定义规范

与被测试项目中的包名一致。

  1. 测试类命名规范

测试类的命名规则是:以 Test 开头,以它要测试的对象的名称结尾,例如
Test+ 被测试的业务、Test+ 被测试的接口、Test+ 被测试的类
另外一种方式是:以 Test 结尾,以它要测试的对象的名称开头,例如
被测试的业务 +Test、被测试的接口 +Test、被测试的类 +Test
视个人习惯而定,为了 case 定位方便,目前测试团队一般用第一种。

  1. 测试用例命名规范

测试用例的命名规则是:test+ 用例操作 _ 条件状态,统一使用 lowerCamelCase 风格,必须遵从驼峰形式。
单词的约定与测试类命名同

  1. 接口测试代码常见约束

(1)数据清理和构造

  • @BeforeClass @Before 中做数据准备等相关操作:加载测试类以前需要加载所有测试用例共同的场景数据,同时在运行单个测试用例的时候加载特别的测试数据。
  • @AfterClass @After 中做测试数据清理等相关操作:在执行完相关测试以后清理用例现场。

(2)断言

  • 不要做无谓的断言
    在测试模式下,有时会情不自禁的滥用断言。这种做法会导致维护更困难,需要极力避免。仅对测试方法名指示的特性进行明确测试,因为对于一般性代码而言,保证测试代码尽可能少是一个重要目标。
  • 使用显式断言方式
    应该总是优先使用 assertEquals(a, b) 而不是 assertTrue(a == b), 因为前者会给出更有意义的测试失败信息。在事先不确定输入值的情况下,这条规则尤为重要。
  • 断言的参数顺序要合适

(3)测试用例保持独立

  • 确保测试代码独立于项目代码之外。
  • 为了保证测试稳定可靠且便于维护,测试用例之间决不能有相互依赖,也不能依赖执行的先后次序。

(4)测试代码要考虑错误处理

  • 如果前面的代码执行失败,后续语句会导致代码崩溃,剩下的测试都无法执行。任何时候都要为测试失败做好准备,避免单个失败的测试项中断整个测试套件的执行。
  • 不要写自己的 catch 代码块,即只有 test 失败的情况,不应该存在 catch 情况。

结语

接口测试是一个非常庞杂的体系,很难用一篇文章阐述清楚,其他实践如接口测试覆盖率统计、标准协议页面化测试平台(提供给没有编码能力的产品或测试人员使用)、maven 项目骨架建立标准化测试工程、dubbo/hessian/restful/webservice 等接口协议具体实现等等限于篇幅也没有做具体阐述。期待大家一起探讨。

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走!

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
 

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
网上这本书的电子版不好这,这是用money换来的——和大家分享! 由于书太大,我把书分成两部分别上传。 内容简介 本书系统全面地介绍了Java中的各项主流技术,以及基于这些技术的商业化应用程序的开发技巧,在讲解过程中以目前最为流行的开发工具MyEclipse为载体,全面系统地介绍了如何在MyEclipse中开发基于Struts、Hibernate、Spring等主流框架的各种Java应用程序。 本书内容主要来自作者多年的软件开发和教学、培训经验,通过实例由浅入深地介绍MyEclipse的基本应用,是一本强调实践技能的实用性指导图书。 本书内容丰富、技术全面、案例实用,而且所有的实例都以MyEclipse工程的形式组织,并按章节的顺序组织在附书光盘中,源代码工程都经过精心调试,可以直接导入MyEclipse中运行。 本书内容精练、重点突出、实例丰富,是Java程序开发人员必备的参考书,同时也可作为高等院校计算机及相关专业的教材。 图书目录 第1章 初识MyEclipse 1 1.1 MyEclipse简介 1 1.2 MyEclipse的安装 1 1.2.1 JDK的安装与配置 1 1.2.2 MyEclipse 7.0的安装和运行 4 1.3 获取和阅读MyEclipse帮助文档 5 1.4 本章小结 5 第2章 MyEclipse集成开发环境的使用 6 2.1 MyEclipse集成开发工具界面 6 2.1.1 MyEclipse的菜单栏 7 2.1.2 MyEclipse的工具栏 13 2.1.3 MyEclipse的透视图 14 2.1.4 MyEclipse的视图 17 2.1.5 MyEclipse的编辑器 20 2.1.6 MyEclipse的Tasks视图 22 2.1.7 MyEclipse的Bookmarks视图 24 2.2 MyEclipse中的资源管理 26 2.2.1 MyEclipse中的工作空间 26 2.2.2 MyEclipse中的Navigator视图 27 2.3 定制MyEclipse的工作台 33 2.3.1 定制工作台外观 34 2.3.2 定制快捷键 35 2.3.3 定制编辑器 36 2.3.4 定制工作台公共设置 36 2.4 MyEclipse中常用操作 36 2.4.1 配置JRE 36 2.4.2 设置编译路径 37 2.4.3 设置项目属性 38 2.5 本章小结 39 第3章 Java程序的开发 40 3.1 使用JDT编写Java项目 40 3.2 MyEclipse中的Java代码编辑器 43 3.2.1 Java代码编辑器基本功能 43 3.2.2 自定义Java代码编辑器 45 3.2.3 Java代码编辑器相关视图 50 3.3 MyEclipse中的Java代码编译器 51 3.4 MyEclipse中的Java代码调试器 52 3.4.1 Java项目的运行 52 3.4.2 Java项目的调试 53 3.5 MyEclipse中的Java代码搜索器 57 3.5.1 搜索功能 57 3.5.2 查找功能 58 3.6 MyEclipse中的Java代码重构支持 59 3.6.1 Java元素重命名 59 3.6.2 Java元素移动 60 3.6.3 Java元素复制 61 3.7 本章小结 61 第4章 Java开发的版本控制及SVN 62 4.1 版本控制与SVN 62 4.2 SVN服务器的安装与配置 62 4.3 MyEclipse连接SVN服务器 63 4.3.1 配置MyEclipse连接SVN服务器 63 4.3.2 将SVN服务器中的项目导入到MyEclipse 64 4.3.3 将MyEclipse中的项目提交到SVN服务器 65 4.4 本章小结 67 第5章 Java开发项目的软件测试工具——JUnit 68 5.1 软件测试简介 68 5.2 JUnit简介 68 5.2.1 JUnit的特点 69 5.2.2 JUnit的常用类和接口 69 5.3 在MyEclipse中设置JUnit 71 5.4 JUnit试 72 5.4.1 JUnit测试用例 72 5.4.2 JUnit试套件 75 5.5 JUnit应用实例:数据库程序单元测试 77 5.6 本章小结 80 第6章 Java Web应用程序的开发 81 6.1 Java Web应用程序概述 81 6.2 Tomcat服务器的安装和配置 82 6.2.1 Tomcat服务器的下载 82 6.2.2 Tomcat服务器
【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 3、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于SSM框架+mysql的电子商城web系统项目源码+项目说明.zip ### 项目内容:SSM(Spring+Springmvc+Mybatis)框架的商城小项目 ##### 技术基础: - **JDK版本**:1.8+ - **Tomcat版本**: 8.5 - **代码编辑器**:`IDEA` - **`Maven`项目管理工具**(这样就只需要引入dependency,maven工具会自动为你下载需要的jar包); 比如你需要`junit`的jar包,直接在`pom.xml`文件中加入下面代码(可以在`maven repository`中找到)就可以了。具体操作请自行百度。 ``` <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> ``` - **数据库**:`MYSQL(5.x.x)`; - **NoSQL**:`Redis`(并不是用的很多); - **其他工具推荐** - 谷歌浏览器 - redisManager:redis管理工具 - postman:接口试 - navicate:数据库可视化连接管理 ##### 简介: 商城分为后台人员管理界面和前台处理服务器两个方面。 实现了登录,邮件注册,redis缓存机制,cookie的历史记录浏览,分页浏览商品,加入购物车,提交订单等等功能。 最精彩的是,如果你刚刚学完基础的SSM框架,那么你就可以跟着视频一起完成这个很nice的小工程了。哈哈,话不多说,让我们进入无尽的学习中吧!(光头不再是梦想:) ) **注**:学习视频并不是`SSM`框架,是由本人在学习了`SSM`框架之后,一步一步跟着视频转化而来。如果有些许错误,还请担待。<br> 在这里感谢黑马程序员的视频资料,感谢前一段时间自己的努力! 感觉不错就给我来个`star`吧!谢谢啦~<br> <br> ##### 资源下载: - [项目视频](https://pan.baidu.com/s/1rnmrioE7HSEaxuElKpjLlA) 提取码:t7hv <br> - [项目`Github`地址](https://github.com/JackyFuu/SSM-Maven-Heima) **数据库表、web页面都在WEB28/资源中:**

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值