专栏首页7DGroup性能工具之代码级性能测试工具ContiPerf

性能工具之代码级性能测试工具ContiPerf

前言

做性能的同学一定遇到过这样的场景:应用级别的性能测试发现一个操作的响应时间很长,然后要花费很多时间去逐级排查,最后却发现罪魁祸首是代码中某个实现低效的底层算法。这种自上而下的逐级排查定位的方法,效率通常都很低,代价也很高。所以,我们就需要在项目早期,对一些关键算法进行代码级别的性能测试,以防止此类在代码层面就可以被发现的性能问题,遗留到最后的系统性能测试阶段才被发现。但是,从实际执行的层面来讲,代码级性能测试并不存在严格意义上的测试工具,通常的做法是:改造现有的单元测试框架

而最常使用的改造方法是:

  • 将原本只会执行一次的单元测试用例连续执行 n 次,这个 n 的取值范围通常是 2000~5000;
  • 统计执行 n 次的平均时间。如果这个平均时间比较长(也就是单次函数调用时间比较长)的话,比如已经达到了秒级,那么通常情况下这个被测函数的实现逻辑一定需要优化。

这里之所以采用执行 n 次的方式,是因为函数执行时间往往是毫秒级的,单次执行的误差会比较大,所以采用多次执行取平均值的做法。

那么有没有现成的这样的测试工具呢?

当然也是有的,比如今天我们介绍的主角-- ContiPerf

ContiPerf 简介

ContiPerf 是一个轻量级的测试工具,基于JUnit 4 开发,可用于效率测试等。可以指定在线程数量和执行次数,通过限制最大时间和平均执行时间来进行性能测试。

官网地址:https://sourceforge.net/p/contiperf/wiki/Home

ContiPerf 使用

接下来我们一起来实践一个例子,

首先,加入 pom 依赖包:

   <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter</artifactId>        </dependency>
        <!--引入 ContiPerf 测试工具-->        <dependency>            <groupId>org.databene</groupId>            <artifactId>contiperf</artifactId>            <version>2.3.4</version>            <scope>test</scope>        </dependency>
        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>            <exclusions>                <exclusion>                    <groupId>org.junit.vintage</groupId>                    <artifactId>junit-vintage-engine</artifactId>                </exclusion>            </exclusions>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency><dependency>        <groupId>junit</groupId>        <artifactId>junit</artifactId>        <scope>test</scope>    </dependency>

这里为了演示,编写了一个简单的测试接口: UnitTestService.java

/** * 测试接口类 * @author zuozewei * */public interface UnitTestService {
    public String process(String msg);
}

实现类:UnitTestServiceImpl.java

@Servicepublic class UnitTestServiceImpl implements UnitTestService {
    /**     * 为了测试,这里直接返回传入的值     */    @Override    public String process(String msg) {        // TODO Auto-generated method stub        return msg;    }}

编写 UnitTestServiceTest 测试类,进入 ContiPerfRule。

/** * 编写接口性能测试类 * @author zuozewei * */@RunWith(SpringRunner.class)@SpringBootTest //SpringBootTest 是springboot 用于测试的注解,可指定启动类或者测试环境等,这里直接默认。public class UnitTestServiceTest {
    @Autowired    UnitTestService testService;
    // 引入 ContiPerf 进行性能测试    @Rule    public ContiPerfRule contiPerfRule = new ContiPerfRule();
    @Test    @PerfTest(invocations = 10000,threads = 100) //100个线程 执行10000次    public void test() {        String msg = "this is a test";        String result = testService.process(msg);        //断言 是否和预期一致        Assert.assertEquals(msg,result);    }}

注意: @Rule 是J unit 提供的一个扩展接口注解,其接口类为:org.junit.rules.MethodRule,注意在 Junit5 中,已经被 TestRule 所替代了。也可以通过对类指定 @PerfTest 和 @Required,表示类中方法的默认设置。 @PerfTest注解:

  • invocations:执行次数n,与线程数量无关,默认值为1
  • threads:线程池数量n,并发执行n个线程
  • duration:重复执行时间n,测试至少执行n毫秒

@Required注解:

  • @Required(throughput = 20):要求每秒至少执行20个测试;
  • @Required(average = 50):要求平均执行时间不超过50ms;
  • @Required(median = 45):要求所有执行的50%不超过45ms;
  • @Required(max = 2000):要求没有测试超过2s;
  • @Required(totalTime = 5000):要求总的执行时间不超过5s;
  • @Required(percentile90 = 3000):要求90%的测试不超过3s;
  • @Required(percentile95 = 5000):要求95%的测试不超过5s;
  • @Required(percentile99 = 10000):要求99%的测试不超过10s;
  • @Required(percentiles = “66:200,96:500”):要求66%的测试不超过200ms,96%的测试不超过500ms。

运行测试,控制台会生成结果:

com.zuozewei.springbootcontiperfdemo.service.UnitTestServiceTest.testsamples: 10000max:     331average: 33.3522median:  30

同时访问:target/contiperf-report/index.html,会生成图表:

图表中的指标:

  • Execution time: 执行时间
  • Throughput: TPS
  • Min. latency: 最小响应时间
  • Average latency: 平均响应时间
  • Median: 响应时间中位数
  • 90%: 90%响应时间范围
  • Max latency: 最大响应时间

小结

这里主要是对 Junit 和 ContiPerf 的使用简单的示例,在单元测试阶段的时候考虑做这种代码级性能测试,肯定会提高 ROI(投入产出比)的,而且代价非常小,希望本文对各位同学都能有所启发。

示例代码:

https://github.com/7DGroup/JMeter-examples/tree/master/contiperf/springboot-contiperf-demo

参考资料: [1]:https://sourceforge.net/p/contiperf/wiki/Home [2]:软件测试52讲 茹炳晟

本文分享自微信公众号 - 7DGroup(Zee_7DGroup)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 测试自动化与自动化测试:差异很重要

    自动化测试是通过自动化(例如一组回归测试)进行特定测试的行为,而不是手动进行,而测试自动化是指自动化跟踪和管理不同测试的过程。

    八音弦
  • PHPUnit 单元测试都不会的 PHPer 没法写出高质量的代码

    单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级...

    猿哥
  • Gartner 2020年十大技术趋势之一:超级自动化

    前不久,Gartner立足于“以人为本的智慧空间”,发布了2020年十大战略性技术趋势,分为两类:

    华章科技
  • 为什么我们在RDO中使用OpenStack包构建的测试[Openstack]

    单元测试用于验证源代码的各个单元是否按照定义的规范工作。虽然这听起来很复杂,但简而言之,这意味着我们要验证源代码的每个部分是否按预期工作,而不必运行它们所属的整...

    用户6667850
  • 中移动分布式存储超级大单出炉,浪潮等唱主角

    近日,中国移动公布了2019年至2020年分布式块存储产品集中采购招标公告。自2017年以来,中国移动已经组织了两次分布式文件存储集采,本次集采是电信运营商行业...

    大数据在线
  • 用junit5编写一个类ZeroCode的测试框

    最近笔者在尝试基于应用日志来自动生成测试用例。这其中就需要一个配套的简易测试框架。梳理了一下,其中的技术点有: 0.使用csv文件来定义测试用例及步骤 1.使用...

    Criss@陈磊
  • 码如其人,同学你能写一手漂亮的Python函数吗

    在机器学习中,我们经常需要使用类和函数定义模型的各个部分,例如定义读取数据的函数、预处理数据的函数、模型架构和训练过程的函数等等。那么什么样的函数才是漂亮的、赏...

    用户2769421
  • Android之APP安全测试篇

    反编译 apk 文件,在AndroidManifest.xml 中查找Activity组件

    洛米唯熊
  • 机器学习的「反噬」:当 ML 用于密码破解,成功率竟然这么高!

    因此,一位好奇的学者 Tikeswar Naik,通过简单的实验和我们讨论了这项技术的某一潜在滥用情况——使用 ML 来破解密码,希望通过这一介绍能够让更多人保...

    AI研习社
  • 修复缺陷的正确姿势

    如果给我一个小时来修复一个缺陷,我会花50分钟来写测试,用剩下的10分钟来改代码 。

    ThoughtWorks

扫码关注云+社区

领取腾讯云代金券