Unity之一:入门指南


本文译自Unity/docs/UnityGettingStartedGuide.md,以及自己使用的总结。

Unity的官网:ThrowTheSwitch.org

获取最新版本的Unity,可以访问:ThrowTheSwitch/Unity

一、欢迎

恭喜,你现在自豪的拥有了自己的一堆bit。你准备对这些0和1做些什么呢?这篇文章将帮助你做相关的决定。

Unity是一个单元测试框架,目标是精简而强大。Unity的内核只有三个文件:一个C文件和两个头文件!它们相互合作提供了许多函数和宏使得测试更容易。

Unity的设计是跨平台的。它尽可能地遵从C标准,同时提供对许多不守规矩的嵌入式C编译器的支持。Unity已被用在许多编译器上,包括GCC、IAR、Clang、Green Hills、 Microchip和MS Visual Studio,将其移植到一个新目标编译器上也不需要太多工作量。

二、文档概览

2.1 Unity入门指南

对应docs/UnityGettingStartedGuide.md,也就是本篇译文。讲解了整个Unity工程目录结构,以及帮助文档概要说明,最后以示例讲解了Unity的简单使用。

2.2 Unity断言参考文档

对应docs/UnityAssertionsReference.md。这篇文档将带你看遍Unity提供的所有断言选项,这将是你单元测试的面包黄油。你将在断言上花费比Unity其他部分更多的时间。

2.3 Unity断言欺骗表

对应docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf。正如文档命名,它是Unity断言参考文档中所有断言的摘要,专门用于打印出来在使用中参考。

2.4 Unity配置向导

对应docs/UnityConfigurationGuide.md。当你需要在新的平台或编译器上使用Unity,需要查看这篇文档。这篇文档详细说明了Unity的所有配置选项,你可以根据你的测试需求定制相关的配置选项。

2.5 Unity辅助脚本

对应docs/UnityHelperScriptsGuide.md,该文档描述了如何利用辅助脚本来简化你的测试工作。这些辅助脚本使用Ruby编写,存放在在auto文件夹中。单独使用Unity并不会用到辅助脚本,它们只是用来简化使用Unity的测试工作而已。

2.6 Unity许可

没有许可证文件的开源项目会是什么?因此,Unity也有License,它描述了你使用Unity时应该同意的条款。我们希望你无论在什么情况下使用,Unity对你都是非常有用的;但如果在使用中遇到了问题,请不要责备我们。

三、文件夹概述

如果你已经通过Github或者其他类似地方获取到了Unity,你可能会被Unity展现的文件吓一跳。别担心,Unity本身是非常小的(前面讲了Unity核心只有三个文件),其他部分仅仅是为了让你的生活变得更好(使用更加简单)而存在。是否忽视还是使用它们,全凭你自己做主。下面是Unity工程的概述:

  • src:这就是你关心的代码,它包含一个C文件和两个头文件,这就是Unity;
  • docs:所有使用方法的文档都放在这里,包括你现在正在阅读的文档;
  • examples:存放了一些Unity的使用示例;
  • extras:这里存放了Unity的外部插件,它们不是Unity工程的核心;如果你是通过阅读James Grenning获取的Unity,你会想了解它;
  • test:这里包含了Unity本身和相关脚本的全部测试。如果你只是使用Unity,这个文件夹你永远不会用到;但如果你是团队中负责将Unity移植到新的工具链的人,这里的测试可以帮助验证你的移植是否都配置好了;
  • auto:你将在这里发现一些可以简化测试工作的Ruby脚本。对于仅是使用Unity来讲,它们完全是可选的。

四、如何创建测试文件

4.1 创建并包含头文件

测试文件都是C文件。大部分情况下,你需要为你的每一个C模块创建一个测试文件,并且这个测试文件需要包含unity.h和C模块对应的头文件

#include "unity.h"
#include "file_to_test.h"

4.2 实现setUp()和tearDown()

接着,一个测试文件需要包含setUp()和tearDown()函数:setUp()函数可以包含每个测试之前需要运行的任何东西;tearDown()函数则包含每个测试之后需要运行的任何东西;这两个函数都不接受任何参数,也不返回任何值

void setUp(void)
{
    // set stuff up here
}

void tearDown(void)
{
    // clean stuff up here
}

++如果你的测试不需要在用例前后做任何事情,你可以保留这两个函数实现为空;如果你移植Unity时,将这两个函数配置为可选的,那么你可以完全不实现它们++。如果不确定现有环境这两个函数是否可选的,试一下就知道了:如果编译器在链接时抱怨说找不到setUp()和tearDown()函数实现,那么就知道需要为它们创建一个空实现了。

4.3 添加测试函数

测试文件的主题是一系列的测试函数。测试文件遵循如下命名规则:以“test_”或spec_开头。当然,你也可以不这样命名,但这样会使其他开发者更加容易看出来哪些是测试函数;而且,Unity和Ceeling中的自动化脚本默认也是去寻找带这种前缀的测试函数。测试函数都不接受任何参数,也不返回任何值。所有测试计数(成功或失败)都由Unity内部处理。

void test_function_should_doBlahAndBlah(void) {
    //test stuff
}

void test_function_should_doAlsoDoBlah(void) {
    //more test stuff
}

4.4 实现主程序main()

最后,在你的测试文件的最后,实现测试主程序main():这个主程序首先调用UNITY_BEGIN(),接着为每个测试调用RUN_TEST(),最后调用UNITY_END()。RUN_TEST()将会触发每个测试函数的运行,所以,你一定要为你的每一个测试调用对应调用RUN_TEST()。

int main(void) {
    UNITY_BEGIN();
    RUN_TEST(test_function_should_doBlahAndBlah);
    RUN_TEST(test_function_should_doAlsoDoBlah);
    return UNITY_END();
}

记住为每个测试都要在主程序main()中添加RUN_TEST()的过程比较单调乏味。如果你喜欢在构建过程中使用辅助脚本,那么你可以考虑使用我们++提供的generate_test_runner.rb脚本:它将自动创建main()主程序,并自动将你的所有测试包含进主程序中++,前提是你遵循了4.3节介绍的测试函数命名规范。在这种情况下,你的测试文件中就不需要实现main()主程序了。

4.5 完整的示例

通过前面的介绍,已经基本满足你的需求了。若想要获取更多的信息,可以查看第二章介绍的相关文档。下面是前面讲述示例的完整代码:

#include "unity.h"
#include "file_to_test.h"

void setUp(void) {
    // set stuff up here
}

void tearDown(void) {
    // clean stuff up here
}

void test_function_should_doBlahAndBlah(void) {
    //test stuff
}

void test_function_should_doAlsoDoBlah(void) {
    //more test stuff
}

int main(void) {
    UNITY_BEGIN();
    RUN_TEST(test_function_should_doBlahAndBlah);
    RUN_TEST(test_function_should_doAlsoDoBlah);
    return UNITY_END();
}

五、如何构建并运行测试文件

在C和C++这样的语言中,学习一个新的单元测试框架,是一个非常大的(single biggest)挑战。C和C++这样的语言很擅长让你“接近金属”(注:意思是接近硬件本质)(为什么要用金属这个词?“接近硅”不是更加准确么?),语言这样的特性通常是非常不错的,不过这也给测试带来了更大的挑战。

对于不同的工具链,你有两个好的选择:在模拟机上运行,还是在电脑上运行。这取决于你来自何方(注:当前开发环境的条件)?你可能会感到惊讶:居然没有在目标硬件上运行的选项!这是有很多原因的,比如:

  • 在硬件上,你有太多的限制(如处理能力、内存等);
  • 在硬件上,你无法完全控制所有的寄存器;
  • 在硬件上,单元测试更加具有挑战;
  • 单元测试并不是系统测试,保持它们的独立性。

大部分开发者选择将单元测试作为本地应用程序(比如使用gcc或MSVC)或模拟器上的应用程序来运行,而不是在真正的硬件上运行。它们都是不错的选择:本地应用程序的优势是配置起来更加简单、快捷;模拟器上的应用程序的优势是使用了与你目标硬件相同的编译器。关于这两个方式的配置项,详见Unity配置向导:UnityConfigurationGuide.md

为了使这两种方式正常运转,你也许需要根据你的目标硬件,对寄存器集文件(比如类型宽度)做一些配置(后面将会讨论)。

构建测试程序,需要链接Unity、测试C文件和对应被测试的C文件,最终会生成一个可执行文件,这个可执行文件就是被测文件对应模块的单元测试集合。对不同的测试模块和测试文件,重复这个过程,分别生成不同的单元测试集合的可执行文件。

将单元测试分离到独立的可执行文件是非常灵活的,这样允许我们:

  • 对我们的系统进行更全面、更彻底的单元测试;
  • 保持所有的测试代码与我们最终发布的产品代码分离。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值