CppTest单元测试框架(更新)

目录

  • 1 背景
  • 2 设计
  • 3 实现
  • 4 使用
    • 4.1 主函数
    • 4.2 使用方法

1 背景

前面文章单元测试之CppTest测试框架中讲述利用宏ADD_SUITE将测试用例自动增加到测试框架中。但在使用中发现一个问题,就是通过宏ADD_SUITE增加多个测试Suite时,每次运行时都是所有测试Suite都运行,有的Suite运行比较慢,这对边写测试用例边编译运行时效率很低。于是就在原来测试框架下作出修改,即默认运行所有测试用例,不过可以通过命令指定测试用例来运行。

2 设计

修改后新的类图如下:
类图

修改说明:

  • TestApp 增加成员suites_,
  • addSuite增加参数name,表示测试Suite名字,该函数实现将suite增加到成员suites_中存起来。
  • run接口没变,实现时从suites_将suite增加到mainSuite_中,如果没指定测试用例则全部增加,否则只增加指定测试用例。
  • AutoAddSuite的构造函数增加参数用例名称。
  • 宏ADD_SUITE参数没变化,实现时将类型作为测试用例名称来注册

类定义如下:

#ifndef TESTAPP_H
#define TESTAPP_H
#include <cpptest/cpptest.h>
#include <map>
#include <memory>

class TestApp
{
    typedef std::map<std::string, std::unique_ptr<Test::Suite>> Suites;
    Test::Suite mainSuite_;
    Suites suites_;
    TestApp();
public:
    static TestApp& Instance();

    void  addSuite(const char* name, Test::Suite * suite);
    int run(int argc, char *argv[]);
};

#define theTestApp TestApp::Instance()

template<typename Suite>
struct AutoAddSuite
{
    AutoAddSuite(const char* Name) { theTestApp.addSuite(Name, new Suite()); }
};

#define ADD_SUITE(Type) AutoAddSuite<Type>  add##Type(#Type);

说明:

  • TestApp类型是单例类,提高增加Suite接口和run接口
  • AutoAddSuite是一个自动添加Suite的模板类型
  • 宏ADD_SUITE定义了AutoAddSuite对象,用于自动添加。

3 实现

#include "testapp.h"

#include <iostream>
#include <tuple>
#include <cstring>
#include <cstdio>

namespace
{
void usage()
{
    std::cout << "usage: test [MODE] [Suite]\n"
         << "where MODE may be one of:\n"
         << "  --compiler\n"
         << "  --html\n"
         << "  --text-terse (default)\n"
         << "  --text-verbose\n";
}

std::tuple<std::string, std::unique_ptr<Test::Output>>
cmdline(int argc, char* argv[])
{
    Test::Output* output = 0;
    std::string name;

    if (argc == 1)
        output = new Test::TextOutput(Test::TextOutput::Verbose);
    if(argc > 1)
    {
        const char* arg = argv[1];
        if (strcmp(arg, "--compiler") == 0)
            output = new Test::CompilerOutput;
        else if (strcmp(arg, "--html") == 0)
            output =  new Test::HtmlOutput;
        else if (strcmp(arg, "--text-terse") == 0)
            output = new Test::TextOutput(Test::TextOutput::Terse);
        else if (strcmp(arg, "--text-verbose") == 0)
            output = new Test::TextOutput(Test::TextOutput::Verbose);
        else if(strcmp(arg, "--help") == 0)
            std::tuple<std::string, std::unique_ptr<Test::Output>>("help", output);
        else
            std::cout << "invalid commandline argument: " << arg << std::endl;
    }
    if(argc > 2)
        name = argv[2];
    return std::tuple<std::string, std::unique_ptr<Test::Output>>(name, output);
}
}

TestApp & TestApp::Instance()
{
    static TestApp theApp;
    return theApp;
}

TestApp::TestApp()
{}

void TestApp::addSuite(const char* name, Test::Suite * suite)
{
    suites_.emplace(name, std::unique_ptr<Test::Suite>(suite));
}

int TestApp::run(int argc, char *argv[])
{
    try
    {
        auto params = cmdline(argc, argv);
        std::string name(std::move(std::get<0>(params)));
        std::unique_ptr<Test::Output> output(std::move(std::get<1>(params)));
        if(name == "help" || !output)
        {
            usage();
            std::cout << "where Suite may be one of(default - all):\n";
            for(auto & suite: suites_)
                std::cout << "  " << suite.first << "\n";
            return 0;
        }

        for(auto & suite: suites_)
        {
            if(name.empty())
                mainSuite_.add(std::move(suite.second));
            else if(name == suite.first)
            {
                mainSuite_.add(std::move(suite.second));
                break;
            }
        }
        mainSuite_.run(*output, true);

        Test::HtmlOutput* const html = dynamic_cast<Test::HtmlOutput*>(output.get());
        if (html)
            html->generate(std::cout, true, argv[0]);
    }
    catch (...)
    {
        std::cout << "unexpected exception encountered\n";
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

说明:

  • Instance 返回一个单例引用
  • addSuite 增加Suite到suites_
  • run
    • 首先根据命令行返回Test::Output和要单独运行测试用例名称
    • 如果参数错误或help显示用法后退出主程序。
    • 遍历suites_,将suite添加到mainSuite_中(如果name不为空,则只添加名称为name的测试用例)
    • 然后调用mainSuite_运行测试用例
    • 最后如果类型是Output是Test::HtmlOutput类型,则将结果输出到标准输出std::cout.

4 使用

4.1 主函数

#include "testapp.h"

int main(int argc, char *argv[])
{
    try
    {
        theTestApp.run(argc, argv);
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
    }
    return 0;
}

主函数很简单,变化。

4.2 使用方法

这里假定程序名称concurrent,显示用法:

 $ ./concurrent --help
usage: test [MODE] [Suite]
where MODE may be one of:
  --compiler
  --html
  --text-terse (default)
  --text-verbose
where Suite may be one of(default - all):
  AtomicSuite
  BlockQueueSuite
  ConditionVariableSuite
  FutureSuite
  LocksSuite
  MutexSuite
  RingQueueSuite
  ThreadSuite
  TimedMutexSuite

运行测试用例BlockQueueSuite:

$ ./concurrent --text-terse BlockQueueSuite
BlockQueueSuite: 0/2
I get a Apple pie
I get a Banana pie
I get a Pear pie
I get a Plum pie
I get a Pineapple pie

I get a Apple pie
I get a Banana pie
I get a Pear pie
I get a Plum pie
I get a Pineapple pie

I get a Apple
I get a Banana
I get a Pear
I get a Plum
I get a Pineapple
BlockQueueSuite: 1/2
I get a Apple pie in thread(3)

I get a Banana pie in thread(4)

I get a Pear pie in thread(0)

I get a Plum pie in thread(2)

I get a Pineapple pie in thread(1)

I get a Apple pie in thread(0)

I get a Banana pie in thread(2)

I get a Pear pie in thread(3)

I get a Plum pie in thread(1)

I get a Pineapple pie in thread(4)

I get a Apple in thread(1)

I get a Banana in thread(0)

I get a Pear in thread(2)

I get a Plum in thread(3)

I get a Pineapple in thread(4)
BlockQueueSuite: 2/2, 100% correct in 0.021808 seconds
Total: 2 tests, 100% correct in 0.021808 seconds

说明:

  • 如上所述只运行测试用例BlockQueueSuite

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/745316.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GraphQL:简介

GraphQL 图片来源&#xff1a; 我们将探索GraphQL 的基础知识&#xff0c;并学习如何使用Apollo将其与 React 和 React Native 等前端框架连接起来。这将帮助您了解如何使用 GraphQL、React、React Native 和 Apollo 构建现代、高效的应用程序。 什么是 GraphQL&#xff1f;…

中国智能工厂自动化集成商100强:广东23家,江苏20家,上海浙江紧随其后

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 更多的海量【智能制造】相关资料&#xff0c;请到智能制造online知识星球自行下载。 在数字化、智能化的浪潮中&#xff0c;中国智能工厂自动化集…

2024年兼职新赛道,我一个插画师给AI打下手,兼职月入3千!

AI生成厉害到什么程度&#xff1f;现在人类已经在为它打下手了。 据一位画手网友分享&#xff0c;他们圈子里已经诞生了全新的工种&#xff01; 虽然乍一看名字别无二致都是“插画师”&#xff0c;但细看工作内容&#xff1a;使用AI绘画然后筛选精修。救&#xff0c;这不妥妥…

小程序中this(1)

}, onLoad: function() {}, }) 此时经过编译后模拟器的显示&#xff1a; 这里都容易理解&#xff0c;当点击了button按钮后&#xff0c;触发点击事件执行testfun函数&#xff0c;将test02设置为8&#xff0c;如图&#xff1a; 通过this.data.test028这种方式直接赋值可以吗&…

如何快速交付网络基础设施运维管理软件项目?

​ 基于nVisual网络基础设施数字孪生管理工具 开发项目需求 项目交付成本节省50%、进度提高100% ​ &#xff1e;&#xff1e;&#xff1e;nVisual主要功能&#xff1c;&#xff1c;&#xff1c; 01 场 景 ★ 支持层次化的场景结构 ★ 支持多种空间场景 ​ 02 规 划 ★ 丰…

[A133]uboot启动流程

[A133]uboot启动流程 hongxi.zhu 2024-6-21 1. 第一阶段 lds描述 从u-boot.lds中能找到程序的汇编入口ENTRY(_start) brandy/brandy-2.0/u-boot-2018/u-boot.lds OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUT…

AU音频重新混合音频,在 Adobe Audition 中无缝延长背景音乐,无缝缩短BGM

导入音频&#xff0c;选中音频&#xff0c;并且点 New Multitrack Session 的图标 设计文件名和存储路径&#xff0c;然后点 OK 点 Essential Sound 面板点 Music &#xff08;如果没有这个面板 点菜单栏 Windows > Essential Sound 调出来&#xff09; 点 Duration 展…

西门子PLC数据 转 CCLink IE Field Basic项目案例

1 案例说明 设置网关采集西门子PLC数据把采集的数据转成CCLink IE Field Basic协议转发给其他系统。 2 VFBOX网关工作原理 VFBOX网关是协议转换网关&#xff0c;是把一种协议转换成另外一种协议。网关可以采集西门子&#xff0c;欧姆龙&#xff0c;三菱&#xff0c;AB PLC&am…

星戈瑞DSPE-FITC在细胞标记中的应用

细胞标记是生物医学研究中的一项基本技术&#xff0c;它允许研究者追踪和观察细胞的行为、分布以及与周围环境的相互作用。在众多的细胞标记方法中&#xff0c;DSPE-FITC因其独特的性质和应用范围而受关注。 DSPE-FITC的基本性质 DSPE-FITC是由二硬脂酰磷脂酰乙醇胺&#xff0…

海云安参编《数字安全蓝皮书 》正式发布并入选《2024中国数字安全新质百强》荣膺“先行者”

近日&#xff0c;国内数字化产业第三方调研与咨询机构数世咨询正式发布了《2024中国数字安全新质百强》&#xff08;以下简称百强报告&#xff09;。海云安凭借在开发安全领域的技术创新力及市场影响力入选百强报告“新质百强先行者” 本次报告&#xff0c;数世咨询经过对国内8…

文心一言使用笔记

目录 让文心一言提炼已有的内容&#xff0c;模仿给出的案例写一段宣传稿方法例子 发现写出的内容有瑕疵&#xff0c;如何微调&#xff1f;比如文心一言介绍的领导不全如何让文心一言检查语法和表达问题&#xff1f; 如何让文心一言将每个片段用一两句话总结&#xff1f;为了防止…

冰淇淋PDF编辑器,轻量,无需安装,打开即用

​IceCream PDF Editor (冰淇淋PDF编辑器) 是一款简单实用的PDF文件编辑工具。功能包括&#xff1a;编辑文本、注释添加、页面管理、PDF文件保护等&#xff1b;操作简单&#xff0c;功能强大&#xff0c;使用户能够轻松编辑和修改PDF文件。 软件链接&#xff1a;轻量&#xff…

华为OD机试【高矮个子排队】(java)(100分)

1、题目描述 现在有一队小朋友&#xff0c;他们高矮不同&#xff0c;我们以正整数数组表示这一队小朋友的身高&#xff0c;如数组{5,3,1,2,3}。 我们现在希望小朋友排队&#xff0c;以“高”“矮”“高”“矮”顺序排列&#xff0c;每一个“高”位置的小朋友要比相邻的位置高或…

Ollama模型部署工具在Linux平台的部署

1.新建普通用户dmx&#xff08;可选&#xff09; [rootnode3 ~]$ useradd dmx2.切换普通用户dmx环境(可选) [dmxnode3 ~]$ su - dmx3.下载ollama-linux-amd64服务 下载ollama-linux-amd64到 ~/server目录&#xff0c;并将ollama-linux-amd64服务重命名为ollamaEED curl -L …

【仿真】UR机器人手眼标定与实时视觉追踪(单目)

这段代码实现了一个机器人视觉引导系统,主要功能包括: 连接仿真环境,控制UR机器人。相机标定: 使用棋盘格图案进行相机内参标定通过移动机器人采集多组图像使用calibrateCamera函数计算相机内参 手眼标定: 采集机器人末端位姿和对应的棋盘格图像使用calibrateHandEye函数计算相…

Percona Toolkit 神器全攻略(配置类)

Percona Toolkit 神器全攻略&#xff08;配置类&#xff09; Percona Toolkit 神器全攻略系列共八篇&#xff0c;前文回顾&#xff1a; 前文回顾Percona Toolkit 神器全攻略Percona Toolkit 神器全攻略&#xff08;实用类&#xff09; 全文约定&#xff1a;$为命令提示符、gr…

51-61 CVPR 2024 最佳论文 | Rich Human Feedback for Text-to-Image Generation

23年12月&#xff0c;加州大学圣地亚哥、谷歌研究院、南加州大学、剑桥大学联合发布Rich Human Feedback for Text-to-Image Generation论文。 作者受大模型中RLHF技术的启发&#xff0c;用人类反馈来改进Stable Diffusion等文生图模型&#xff0c;提出了先进的RichHF-18K数据…

批归一化(Batch Normalization)和层归一化(Layer Normalization)的作用

在深度学习领域&#xff0c;归一化技术被广泛用于加速神经网络的训练速度并提高其稳定性。本文将介绍两种常见的归一化方法&#xff1a;批归一化&#xff08;Batch Normalization, BN&#xff09;和层归一化&#xff08;Layer Normalization, LN&#xff09;&#xff0c;并通过…

在虚拟机中安装centos系统,及通过安装包安装jdk1.8,mysql5.7,redis7.2

在虚拟机中安装centos系统&#xff0c;及通过安装包安装jdk1.8,mysql5.7,redis7.2 第一章 CentOS7的下载1.1.使用阿里云开源镜像站下载。 第二章 CentOS7的配置2.1.通过VMware 创建一个CentOS7虚拟机2.1.1.打开软件&#xff0c;点击如箭头所示按钮&#xff0c;创建虚拟机2.1.2.…

【建设方案】智慧园区大数据云平台建设方案(DOC原件)

大数据云平台建设技术要点主要包括以下几个方面&#xff1a; 云计算平台选择&#xff1a;选择安全性高、效率性强、成本可控的云计算平台&#xff0c;如阿里云、腾讯云等&#xff0c;确保大数据处理的基础环境稳定可靠。 数据存储与管理&#xff1a;利用Hadoop、HBase等分布式…