CMake:测试的其他补充(重要)

2023-09-21 09:40:34

导言

通过前几篇的学习,我们基本掌握了关于单元测试的相关内容。当然,随着技术的不断发展,根据不同业务的需求测试框测出不穷,我们没有办法一一列举。本篇我们将补充几个测试的相关技术,如预期测试失败、并行测试以及测试子集等。

预期测试失败

理想情况下,我们希望所有的测试能在每个平台上通过。然而,也可能想要测试预期的失败或异常是否会在受控的设置中进行。这种情况下,我们将把预期的失败定义为成功。我们认为,这通常应该交给测试框架(例如:Catch2Google Test)的任务,它应该检查预期的失败并向CMake报告成功。但是,在某些情况下,可能希望将测试的非零返回代码定义为成功;换句话说,可能想要颠倒成功和失败的定义。

项目结构

.
├── CMakeLists.txt
└── test.py

项目地址:

https://gitee.com/jiangli01/tutorials/tree/master/cmake-tutorial/chapter4/05

CMakeLists.txt

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(test_error LANGUAGES NONE)

find_package(PythonInterp REQUIRED)

enable_testing()

add_test(example ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test.py)

set_tests_properties(example PROPERTIES WILL_FAIL true)

定义测试并告诉CMake,测试预期会失败:

set_tests_properties(example PROPERTIES WILL_FAIL true)

相关源码

test.py

import sys
# simulate a failing test
sys.exit(1)

输出结果

Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/05/build
    Start 1: example
1/1 Test #1: example ..........................   Passed    0.01 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   0.02 sec

使用超时测试运行时间过长的测试

理想情况下,测试集应该花很短的时间进行,以便开发人员经常运行测试,并使每个提交(变更集)进行测试成为可能(或更容易)。然而,有些测试可能会花费更长的时间或者被卡住(例如,由于高文件I/O负载),可能需要设置超时来终止耗时过长的测试,它们延迟了整个测试,并阻塞了部署管道。本节,将通过一种设置超时的方法,可以针对每个测试设置不同的超时。

项目结构

.
├── CMakeLists.txt
└── test.py

项目地址:

https://gitee.com/jiangli01/tutorials/tree/master/cmake-tutorial/chapter4/06

CMakeLists.txt

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(test_long_test LANGUAGES NONE)

find_package(PythonInterp REQUIRED)

enable_testing()

add_test(example ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test.py)
set_tests_properties(example PROPERTIES TIMEOUT 10)
set_tests_properties(example PROPERTIES TIMEOUT 10)

为测试指定时限,设置为10秒

相关源码

test.py

import sys
import time
# wait for 2 seconds
time.sleep(2)
# report success
sys.exit(0)

输出结果

mkdir build & cd build
cmake ..
ctest
Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/06/build
    Start 1: example
1/1 Test #1: example ..........................   Passed    2.01 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   2.02 sec

为了验证超时是否有效,将test.py中的sleep命令增加到11秒,并重新运行测试:

Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/06/build
    Start 1: example
1/1 Test #1: example ..........................***Timeout  10.02 sec

0% tests passed, 1 tests failed out of 1

Total Test time (real) =  10.02 sec

The following tests FAILED:
          1 - example (Timeout)
Errors while running CTest

并行测试

大多数现代计算机都有4个或更多个CPU核芯。CTest有个非常棒的特性,能够并行运行测试,如果有多个可用的核。这可以减少测试的总时间。

项目结构

.
├── CMakeLists.txt
└── test
    ├── a.py
    ├── b.py
    ├── c.py
    ├── d.py
    ├── e.py
    ├── f.py
    ├── g.py
    ├── h.py
    ├── i.py
    └── j.py

项目地址:

https://gitee.com/jiangli01/tutorials/tree/master/cmake-tutorial/chapter4/07

CMakeLists.txt

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)

project(recipe-08 LANGUAGES NONE)

find_package(PythonInterp REQUIRED)

enable_testing()
add_test(a ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/a.py)
add_test(b ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/b.py)
add_test(c ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/c.py)
add_test(d ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/d.py)
add_test(e ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/e.py)
add_test(f ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/f.py)
add_test(g ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/g.py)
add_test(h ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/h.py)
add_test(i ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/i.py)
add_test(j ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/j.py)

相关源码

这里我们只给出了一个python文件,其他文件按照如下表格设置时间即可。
在这里插入图片描述
a.py

import sys
import time
# wait for 0.5 seconds
time.sleep(0.5)
# finally report success
sys.exit(0)

输出结果

mkdir build & cd build
cmake ..
ctest
Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/07/build
      Start  1: a
 1/10 Test  #1: a ................................   Passed    0.51 sec
      Start  2: b
 2/10 Test  #2: b ................................   Passed    0.52 sec
      Start  3: c
 3/10 Test  #3: c ................................   Passed    0.52 sec
      Start  4: d
 4/10 Test  #4: d ................................   Passed    0.52 sec
      Start  5: e
 5/10 Test  #5: e ................................   Passed    1.52 sec
      Start  6: f
 6/10 Test  #6: f ................................   Passed    1.52 sec
      Start  7: g
 7/10 Test  #7: g ................................   Passed    1.52 sec
      Start  8: h
 8/10 Test  #8: h ................................   Passed    2.52 sec
      Start  9: i
 9/10 Test  #9: i ................................   Passed    3.52 sec
      Start 10: j
10/10 Test #10: j ................................   Passed    4.52 sec

100% tests passed, 0 tests failed out of 10

Total Test time (real) =  17.20 sec
ctest --parallel 4
Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/07/build
      Start 10: j
      Start  9: i
      Start  8: h
      Start  7: g
 1/10 Test  #7: g ................................   Passed    1.51 sec
      Start  6: f
 2/10 Test  #8: h ................................   Passed    2.51 sec
      Start  5: e
 3/10 Test  #6: f ................................   Passed    1.51 sec
      Start  4: d
 4/10 Test  #9: i ................................   Passed    3.52 sec
      Start  3: c
 5/10 Test  #4: d ................................   Passed    0.51 sec
      Start  2: b
 6/10 Test  #5: e ................................   Passed    1.51 sec
      Start  1: a
 7/10 Test  #3: c ................................   Passed    0.51 sec
 8/10 Test  #2: b ................................   Passed    0.51 sec
 9/10 Test #10: j ................................   Passed    4.51 sec
10/10 Test  #1: a ................................   Passed    0.51 sec

100% tests passed, 0 tests failed out of 10

Total Test time (real) =   4.54 sec
ctest --parallel 8
Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/07/build
      Start 10: j
      Start  9: i
      Start  8: h
      Start  7: g
      Start  6: f
      Start  5: e
      Start  4: d
      Start  2: b
 1/10 Test  #4: d ................................   Passed    0.52 sec
      Start  3: c
 2/10 Test  #2: b ................................   Passed    0.52 sec
      Start  1: a
 3/10 Test  #3: c ................................   Passed    0.51 sec
 4/10 Test  #1: a ................................   Passed    0.51 sec
 5/10 Test  #7: g ................................   Passed    1.52 sec
 6/10 Test  #6: f ................................   Passed    1.52 sec
 7/10 Test  #5: e ................................   Passed    1.52 sec
 8/10 Test  #8: h ................................   Passed    2.52 sec
 9/10 Test  #9: i ................................   Passed    3.52 sec
10/10 Test #10: j ................................   Passed    4.52 sec

100% tests passed, 0 tests failed out of 10

Total Test time (real) =   4.52 sec

运行测试子集

前几节,我们学习了如何在CMake的帮助下并行运行测试,并讨论了从最长的测试开始是最高效的。虽然,这种策略将总测试时间最小化,但是在特定特性的代码开发期间,或者在调试期间,我们可能不希望运行整个测试集。对于调试和代码开发,我们只需要能够运行选定的测试子集。t通过本节我们对这一策略进行进一步探究。

项目结构

.
├── CMakeLists.txt
└── test
    ├── benchmark-a.py
    ├── benchmark-b.py
    ├── feature-a.py
    ├── feature-b.py
    ├── feature-c.py
    └── feature-d.py

项目地址:

https://gitee.com/jiangli01/tutorials/tree/master/cmake-tutorial/chapter4/08

CMakeLists.txt

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)

project(test_subset LANGUAGES NONE)

find_package(PythonInterp REQUIRED)

enable_testing()
add_test(
  NAME feature-a
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/feature-a.py
)

add_test(
  NAME feature-b
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/feature-b.py
)

add_test(
  NAME feature-c
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/feature-c.py
)

add_test(
  NAME feature-d
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/feature-d.py
)

add_test(
  NAME benchmark-a
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/benchmark-a.py
)

add_test(
  NAME benchmark-b
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/benchmark-b.py
)

set_tests_properties(
  feature-a
  feature-b
  feature-c
  PROPERTIES
      LABELS "quick"
)

set_tests_properties(
  feature-d
  benchmark-a
  benchmark-b
  PROPERTIES
      LABELS "long"
)

给较短的测试贴上quick的标签,给较长的测试贴上long的标签:

set_tests_properties(
  feature-a
  feature-b
  feature-c
  PROPERTIES
      LABELS "quick"
)

set_tests_properties(
  feature-d
  benchmark-a
  benchmark-b
  PROPERTIES
      LABELS "long"
)

相关源码

我们假设总共有六个测试:前三个测试比较短,名称分别为feature-afeature-bfeature-c,还有三个长测试,名称分别是feature-dbenchmark-abenchmark-b。我们只给出feature-a.py,其他知识睡眠时间的不同。

import sys
import time
# wait for 0.1 seconds
time.sleep(1)
# finally report success
sys.exit(0)

输出结果

ctest -R feature
Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/08/build
    Start 1: feature-a
1/4 Test #1: feature-a ........................   Passed    0.11 sec
    Start 2: feature-b
2/4 Test #2: feature-b ........................   Passed    0.11 sec
    Start 3: feature-c
3/4 Test #3: feature-c ........................   Passed    0.11 sec
    Start 4: feature-d
4/4 Test #4: feature-d ........................   Passed    1.01 sec

100% tests passed, 0 tests failed out of 4

Label Time Summary:
long     =   1.01 sec*proc (1 test)
quick    =   0.33 sec*proc (3 tests)

Total Test time (real) =   1.36 sec
ctest -L long
Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/08/build
    Start 4: feature-d
1/3 Test #4: feature-d ........................   Passed    1.01 sec
    Start 5: benchmark-a
2/3 Test #5: benchmark-a ......................   Passed    1.01 sec
    Start 6: benchmark-b
3/3 Test #6: benchmark-b ......................   Passed    1.01 sec

100% tests passed, 0 tests failed out of 3

Label Time Summary:
long    =   3.04 sec*proc (3 tests)

Total Test time (real) =   3.04 sec
ctest -L quick
Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/08/build
    Start 1: feature-a
1/3 Test #1: feature-a ........................   Passed    0.11 sec
    Start 2: feature-b
2/3 Test #2: feature-b ........................   Passed    0.11 sec
    Start 3: feature-c
3/3 Test #3: feature-c ........................   Passed    0.12 sec

100% tests passed, 0 tests failed out of 3

Label Time Summary:
quick    =   0.34 sec*proc (3 tests)

Total Test time (real) =   0.34 sec

使用测试固件

本节将学习如何使用测试固件。这对于更复杂的测试非常有用,这些测试需要在测试运行前进行设置,以及在测试完成后执行清理操作(例如:创建示例数据库、设置连接、断开连接、清理测试数据库等等)。我们需要运行一个设置或清理操作的测试,并能够以一种可预测和健壮的方式自动触发这些步骤,而不需要引入代码重复。这些设置和清理步骤可以委托给测试框架(例如Google TestCatch2)。

项目结构

.
├── CMakeLists.txt
└── test
    ├── cleanup.py
    ├── feature-a.py
    ├── feature-b.py
    └── setup.py

项目地址:

https://gitee.com/jiangli01/tutorials/tree/master/cmake-tutorial/chapter4/09

CMakeLists.txt

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)

project(test_firmware LANGUAGES NONE)

find_package(PythonInterp REQUIRED)

enable_testing()

add_test(
  NAME setup
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/setup.py
)

set_tests_properties(
  setup
  PROPERTIES
    FIXTURES_SETUP my-fixture
)

add_test(
  NAME feature-a
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/feature-a.py
)

add_test(
  NAME feature-b
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/feature-b.py
)

set_tests_properties(
  feature-a
  feature-b
  PROPERTIES
    FIXTURES_REQUIRED my-fixture
)

add_test(
  NAME cleanup
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/cleanup.py
)

set_tests_properties(
  cleanup
  PROPERTIES
    FIXTURES_CLEANUP my-fixture
)
add_test(
  NAME setup
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/setup.py
  )
set_tests_properties(
  setup
  PROPERTIES
      FIXTURES_SETUP my-fixture
  )
add_test(
  NAME feature-a
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/feature-a.py
  )
add_test(
  NAME feature-b
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/feature-b.py
  )
set_tests_properties(
  feature-a
  feature-b
  PROPERTIES
      FIXTURES_REQUIRED my-fixture
  )
add_test(
  NAME cleanup
  COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/cleanup.py
  )
set_tests_properties(
  cleanup
  PROPERTIES
      FIXTURES_CLEANUP my-fixture
  )

定义了一个文本固件,并将其称为my-fixture。我们为安装测试提供了FIXTURES_SETUP属性,并为清理测试了FIXTURES_CLEANUP属性,并且使用FIXTURES_REQUIRED,我们确保测试feature-afeature-b都需要安装和清理步骤才能运行。将它们绑定在一起,可以确保在定义良好的状态下,进入和离开相应的步骤。

相关源码

setup.py

import sys

print("tearing down")

# report success
sys.exit(0)

feature-a.py

import sys

print("running test a")

# report success
sys.exit(0)

feature-b.py

import sys

print("running test b")

# report success
sys.exit(0)

clearup.py

import sys

print("tearing down")

# report success
sys.exit(0)

输出结果

ctest
Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/09/build
    Start 1: setup
1/4 Test #1: setup ............................   Passed    0.01 sec
    Start 2: feature-a
2/4 Test #2: feature-a ........................   Passed    0.01 sec
    Start 3: feature-b
3/4 Test #3: feature-b ........................   Passed    0.01 sec
    Start 4: cleanup
4/4 Test #4: cleanup ..........................   Passed    0.01 sec

100% tests passed, 0 tests failed out of 4

Total Test time (real) =   0.05 sec
ctest -R feature-a
Test project /home/jiangli/repo/tutorials/cmake-tutorial/chapter4/09/build
    Start 1: setup
1/3 Test #1: setup ............................   Passed    0.01 sec
    Start 2: feature-a
2/3 Test #2: feature-a ........................   Passed    0.01 sec
    Start 4: cleanup
3/3 Test #4: cleanup ..........................   Passed    0.01 sec

100% tests passed, 0 tests failed out of 3

Total Test time (real) =   0.03 sec

最后,希望大家变得更强!!!

更多推荐

【每日一题】852. 山脉数组的峰顶索引

852.山脉数组的峰顶索引-力扣(LeetCode)符合下列属性的数组arr称为山脉数组:arr.length>=3存在i(0<i<arr.length-1)使得:arr[0]<arr[1]<...arr[i-1]<arr[i]arr[i]>arr[i+1]>...>arr[arr.length-1]给你由整数组成的山

数据结构——二叉树提升

二叉树题型练习前言一、节点个数以及高度等二、二叉树OJ题二叉树的前序遍历二叉树的中序遍历二叉树的后序遍历单值二叉树二叉树最大深度检查两颗树是否相同.翻转二叉树对称二叉树另一颗树的子树总结前言现在我们开始一轮新的自我提升吧!二叉树的题目当然也更有难度!没有什么是生来就会的,尤其是代码这一方面更是讲究熟能生巧,现在的我们学

全能电子地图下载器3.0-下载离线地图瓦片

前言vue项目要部署到局域网内,不使用在线地图,而是离线地图,寻求了很多的解决方案,最终决定使用离线地图瓦片+leaflet.js实现效果!正文首先需要下载正版的软件,目前我实用的是V3.0版本的,可能和之前的有部分差异化,这个也属于正常。一、下载1.有CSDN会员下载渠道:https://download.csdn.

Vue入门--vue的生命周期

一.什么是Vue二.Vue的简介官方网址特点三.前后端的分离重大问题优势4.Vue入门定义一个管理边界​编辑测试结果vue的优势​编辑测试结果5.Vue的生命周期vue的生命周期图​编辑建立一个html测试结果一.什么是VueVue是一种流行的JavaScript前端框架,用于构建用户界面。它被设计为一种渐进式框架,可

CTF —— 网络安全大赛(这不比王者好玩吗?)

前言随着大数据、人工智能的发展,人们步入了新的时代,逐渐走上科技的巅峰。\⚔科技是一把双刃剑,网络安全不容忽视,人们的隐私在大数据面前暴露无遗,账户被盗、资金损失、网络诈骗、隐私泄露,种种迹象表明,随着互联网的发展,网络安全需要引起人们的重视。\互联网安全从其本质上来讲就是互联网上的信息安全。从广义来说,凡是涉及到互联

3.2 Android eBPF程序类型

写在前面为什么要先了解eBPF程序类型?从帮助函数中,我们可能基于内核的eBPF开放API,对eBPF的能力有一个比较细致的认识,但是这并不能让我们从全局,或者更概括的认识eBPF。eBPF程序类型能够更宏观的告诉我们,eBPF能做哪些事情(除网络相关)。一,eBPF程序类型内核中不同事件会触发不同类型的eBPF程序,

什么是Webpack的Tree Shaking?它的作用是什么?

聚沙成塔·每天进步一点点⭐专栏简介⭐Webpack的TreeShaking⭐作用和原理⭐使用TreeShaking⭐写在最后⭐专栏简介前端入门之旅:探索Web开发的奇妙世界欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些

简单 php结合WebUploader实现文件上传功能

WebUploader资源下载http://fex.baidu.com/webuploader/download.htmlWebUploader使用方法http://fex.baidu.com/webuploader/getting-started.htmlphp上传代码<?phpheader('Content-typ

MFC主框架和视类PreCreateWindow()函数学习

在VC++生成的单文档应用程序中,主框架类和视类均具有PreCreateWindow函数;从名字可知,可在此函数中添加一些代码,来控制窗口显示后的效果;并且它有注释说明,ModifytheWindowclassorstylesherebymodifyingtheCREATESTRUCTcs在这里通过修改CREATEST

​Qt for Python 入门¶​

本页重点介绍如何从源代码构建QtforPython,如果你只想安装PySide2。与你需要运行:pippipinstallpyside2有关更多详细信息,请参阅我们的快速入门指南。此外,您可以查看与项目相关的常见问题解答。一般要求¶Python:3.5+和2.7Qt:建议使用5.12+libclang:libclang

Leetcode.486 预测赢家

题目链接Leetcode.486预测赢家mid题目描述给你一个整数数组nums。玩家111和玩家222基于这个数组设计了一个游戏。玩家111和玩家222轮流进行自己的回合,玩家111先手。开始时,两个玩家的初始分值都是000。每一回合,玩家从数组的任意一端取一个数字(即,nums[0]nums[0]nums[0]或nu

热文推荐