译者注:译者博客(http://blog.csdn.net/lin_strong),转载请保留这条。此为CMock使用手册的翻译,仅供学习交流使用,请勿用于商业用途。
翻译的资料是公开的,在docs/CMock_Summary.md,我想应该不会有什么版权问题,如涉及版权问题,请联系我删除文章。

文章目录

  • CMock: 概述
    • 我们这里到底在说些什么?
  • 安装
  • 生成Mock模块概述
    • Expect:
    • ExpectAnyArgs:
    • Array:
    • Ignore:
    • Ignore Arg:
    • ReturnThruPtr:
    • Callback:
    • Cexception:
  • 运行CMock
    • 从命令行进行Mocking
    • 从脚本文件或Rake进行Mocking
    • 配置选项:
    • 编译选项:
  • 例子
  • 以下为中英对照版
  • CMock: A Summary
    • What Exactly Are We Talking About Here?
  • Installing
  • Generated Mock Module Summary
    • Expect:
    • ExpectAnyArgs:
    • Array:
    • Ignore:
    • Ignore Arg:
    • ReturnThruPtr:
    • Callback:
    • Cexception:
  • Running CMock
    • Mocking from the Command Line
    • Mocking From Scripts or Rake
    • Config Options:
    • Compiled Options:
  • Examples

CMock: 概述

ThrowTheSwitch.org

This documentation is released under a Creative Commons 3.0 Attribution Share-Alike License

我们这里到底在说些什么?

CMock是一个很棒的小工具,它翻了翻你的头文件,然后为其创建出一个mock接口,这样你就可以很方便的
对依赖于其他模块的模块进行单元测试。对于你的头文件中的每个函数原型,像这个:

    int DoesSomething(int a, int b);

你会得到一个自动生成的DoesSomething函数,你可以链接其来替代你真正的DoesSomething函数。
通过使用这个Mocked版本,你可以验证它收到了你想要的数据,并使其返回任何你想返回的数据,
或使其抛出异常,以及其他好玩的……为你被测模块依赖的所有东西创建mock,你会发现你如此nb,
掌控一切:你可以控制和验证被测模块的所有细节。

为了使这更简单,CMock还给你了一堆函数,如下面这样的,这样你就可以告知生成的DoesSomething
函数在每个测试中应该做什么:

    void DoesSomething_ExpectAndReturn(int a, int b, int toReturn);void DoesSomething_ExpectAndThrow(int a, int b, EXCEPTION_T error);void DoesSomething_StubWithCallback(CMOCK_DoesSomething_CALLBACK YourCallback);void DoesSomething_IgnoreAndReturn(int toReturn);

你可以连续调用它们,它会记住你的期望的顺序,像这样:

    test_CallsDoesSomething_ShouldDoJustThat(void){DoesSomething_ExpectAndReturn(1,2,3);DoesSomething_ExpectAndReturn(4,5,6);DoesSomething_ExpectAndThrow(7,8, STATUS_ERROR_OOPS);CallsDoesSomething( );}

这个测试会调用CallsDoesSomething,即我们正在测试的函数。我们期望这函数调用DoesSomething
上次。第一次,我们验证它是按DoesSomething(1, 2)这样调用的,并且返回给其3.第二次,我们验
证它是按DoesSomething(4, 5)这样调用的,并返回给其6.第三次,我们验证它是按
DoesSomething(7, 8)这样调用的,并不返回任何东西直接抛出一个错误。如果CallsDoesSomething
做错了任何事情,测试就会失败。调用DoesSomething次数太少或太多,调用的参数不对或顺序不对
都会导致失败。

CMock是基于Unity的,它使用Unity实现所有的内部测试。
它使用Ruby来做所有的主要工作(版本 2.0.0 及以上)

安装

安装CMock的首件事就是获得一份Ruby的副本。如果你用linux或osx,你很可能已经有了。可以通过
在命令行中输入以下东西来验证:

ruby --version

如果答复显示你没有ruby的话,那你得去安装它了。你可以在ruby-lang
获得最新版本。如果答复显示ruby的版本比2.0.0旧的话,你同样得去升级ruby了。快,我们等你。

一旦你有了Ruby,你有三个选择:

  • 克隆最新版github上的CMock仓储
  • 下载最新版github上的CMock zip
  • 通过在命令行中输入gem install ceedling安装Ceedling(内建了CMock)

生成Mock模块概述

除了mocks自身外,CMock还会生成以下函数以用于你自己的测试中。expect函数总是会生成的。其他函数
则只在启用了对应插件时才会生成。

Expect:

在你使用CMock中最常使用的就是Expect系列函数了。调用它,你就是在告诉CMock你期望在你的测试中
这个函数会被调用。它还指定了你期望它被调用时传递的是哪个参数,以及应该返回哪个值。你可以连续
多次调用这个函数以指定多次调用的顺序。

  • void func(void) => void func_Expect(void)
  • void func(params) => void func_Expect(expected_params)
  • retval func(void) => void func_ExpectAndReturn(retval_to_return)
  • retval func(params) => void func_ExpectAndReturn(expected_params, retval_to_return)

ExpectAnyArgs:

这个的行为就好像Expect,除了它并不真正关心mock被调用时传递的参数是什么。它仍会计数被调用的次数,
并且如果有返回值的话,仍会处理返回值。

  • void func(void) => void func_ExpectAnyArgs(void)
  • void func(params) => void func_ExpectAnyArgs(void)
  • retval func(void) => void func_ExpectAnyArgsAndReturn(retval_to_return)
  • retval func(params) => void func_ExpectAnyArgsAndReturn(retval_to_return)

Array:

ExpectWithArray是Expect的另一种变化。跟expect一样,它关心mock被调用的次数,被调用时传递的参数,
以及它要返回什么值。但这个变化有另一个特性。对于任何参数中有指针或者数组的函数,它会把这参数分
为两个参数。第一个是原来的指针。第二个指明数组中要验证的元素的个数。如果你指定了1,它会验证一个
对象。如果指定了2,它会假设你的指针指向一个数组中的头两个元素。如果你指定了0个元素,当配置了
:smart模式,它只会检查指针,当配置了:compare_data,就会直接失败。

  • void func(void) => (nothing. In fact, an additional function is only generated if the params list contains pointers)
  • void func(ptr * param, other) => void func_ExpectWithArray(ptr* param, int param_depth, other)
  • retval func(void) => (nothing. In fact, an additional function is only generated if the params list contains pointers)
  • retval func(other, ptr* param) => void func_ExpectWithArrayAndReturn(other, ptr* param, int param_depth, retval_to_return)

Ignore:

也许你不关心一个特定函数被调用的次数或被调用时的实参。这种情况下,你会想要使用Ignore。
Ignore在每个测试中只需要调用一次。然后它将忽视之后对那个特定mock的任何调用。IgnoreAndReturn的工作
方式很相似,除了它还知道万一调用发生了,应该返回什么值。如果mock被调用的次数超过了IgnoreAndReturn
被调用的次数,它会不断返回最后一次被调用时指定的那个值,这不会导致失败。如果被调用的次数少了,
也没有任何问题。你就是想要表达你不关心它被调用了多少次,对吧?

  • void func(void) => void func_Ignore(void)
  • void func(params) => void func_Ignore(void)
  • retval func(void) => void func_IgnoreAndReturn(retval_to_return)
  • retval func(params) => void func_IgnoreAndReturn(retval_to_return)

Ignore Arg:

也许你想使用Expect以及它所有的变化,但是你不关心传了什么参数。这在参数是一个指针,指向要由函数来
填充值的位置时特别有用。因为你仍然关心其他参数,你并不想使用ExpectAnyArgs。因此,取而代之的,在
你调用任何expect之前,你可以调用这个函数。它使CMock在接下来的这个测试中忽略这个mock函数的特定参数。

  • void func(params) => void func_IgnoreArg_paramName(void)

ReturnThruPtr:

另一个操作函数的一个特定参数的选择是ReturnThruPtr插件。对于每个像指针或引用的参数,CMock都会生成
这个函数的一个实例。就如AndReturn函数支持注入一个或多个返回值到一个队列中,这个函数让你指定一个或
多个返回值,返回值们会被队列化并拷贝进一个区域,每次mock被调用时会指向对应空间。

  • void func(param1) => void func_ReturnThruPtr_paramName(val_to_return)
  • => void func_ReturnArrayThruPtr_paramName(cal_to_return, len)
  • => void func_ReturnMemThruPtr_paramName(val_to_return, size)

Callback:

如果其他选择都不够用,你确实想要定制一些东西,那还有一个杀招。一旦你在一个测试中stub了一个回调函数,
每当mock被调用,他都会去调用回调函数并返回回调函数中返回的值(如果有返回值的话),而不是进行通常的expect
检查。他可以被配置为先检查参数(就像expects一样)或者也可以直接跳到回调函数。

  • void func(void) => void func_StubWithCallback(CMOCK_func_CALLBACK callback)
    where CMOCK_func_CALLBACK looks like: void func(int NumCalls)
  • void func(params) => void func_StubWithCallback(CMOCK_func_CALLBACK callback)
    where CMOCK_func_CALLBACK looks like: void func(params, int NumCalls)
  • retval func(void) => void func_StubWithCallback(CMOCK_func_CALLBACK callback)
    where CMOCK_func_CALLBACK looks like: retval func(int NumCalls)
  • retval func(params) => void func_StubWithCallback(CMOCK_func_CALLBACK callback)
    where CMOCK_func_CALLBACK looks like: retval func(params, int NumCalls)

Cexception:

最后,如果你使用Cexception来处理异常,你可以使用它来从内部mocks抛出错误。正如Expect,它会记得应该在
哪次调用抛出错误,并且它仍然会先检查参数。

  • void func(void) => void func_ExpectAndThrow(value_to_throw)
  • void func(params) => void func_ExpectAndThrow(expected_params, value_to_throw)
  • retval func(void) => void func_ExpectAndThrow(value_to_throw)
  • retval func(params) => void func_ExpectAndThrow(expected_params, value_to_throw)

运行CMock

CMock是一个Ruby脚本和类。因此你可以直接从命令行使用它,或者也可以把它包含在自己的脚本或者rakefiles中。

从命令行进行Mocking

在解压CMock后,你可以在’lib’路径中找到cmock.rb。
这就是你想要运行的文件。它的参数是你想要mock的多个头文件,以及可选的yaml文件来
进行更细节的配置(详见下方的配置选项)。

比如,这样就能使用MyConfig.yml中的配置创建三个mocks。

ruby cmock.rb -oMyConfig.yml super.h duper.h awesome.h

这将使用默认配置创建两个mock。

ruby cmock.rb ../mocking/stuff/is/fun.h ../try/it/yourself.h

从脚本文件或Rake进行Mocking

CMock可以从你自己的脚本或从一个rakefile中间接的使用。
先include cmock.rb,然后创建一个CMock的实例。
当你创建了自己的实例,有三种方式可以初始化它。

你可以什么都不指定,让它使用默认配置运行:

require 'cmock.rb'
cmock = CMock.new

你可以指定一个YAML文件,其中包含你想要的配置选项:

cmock = CMock.new('../MyConfig.yml')

你可以明确地指定选项:

cmock = Cmock.new(:plugins => [:cexception, :ignore], :mock_path => 'my/mocks/')

配置选项:

以下配置选项可以指定在yaml文件中,或者在实例化时间接指定。

在Ruby中传参时,看起来像这样。

    { :attributes => [“__funky”, “__intrinsic”], :when_ptr => :compare }

定义在yaml文件中时,看起来更像这样。

    :cmock::attributes:- __funky- __intrinsic:when_ptr: :compare

所有情况下,你都可以仅包含那些你想要覆盖默认配置的选项。后面我们会试着说明哪些是默认的。

  • :attributes:
    这里指定了CMock为了测试目的,应该忽略掉的属性。定制的编译器扩展以及externs就是要放在这里的东西。
    如果你的编译器因为一些扩展的语法而编译出问题了,你可以来看看这里。

    • 默认: [’__ramfunc’, ‘__irq’, ‘__fiq’, ‘register’, ‘extern’]
    • 注意 这个选择会在mock的调用中重新插入这些属性。
      如果这不是你想要的,看看:strippables
  • :c_calling_conventions:
    类似地,CMock可能需要理解在你的代码中可能会出现哪个C调用约定。如果它遇到了一些它不认识的,
    它不打算mock它。我们已经默认写了一些最常用的,但是还有许多编译器,因此可能有更多选项。

    • 默认: [’__stdcall’, ‘__cdecl’, ‘__fastcall’]
    • 注意 这个选择会在mock的调用中重新插入这些属性。
      如果这不是你想要的,看看:strippables
  • :callback_after_arg_check:
    通过将这个设置为true来告诉:callback插件在它调用回调函数之前先进行正常的参数检查。
    当设置为false时,就会直接调用回调函数,而不会进行参数验证。

    • 默认: false
  • :callback_include_count:
    要求:callback插件包含一个额外的参数来告知回调函数它已被调用几次了。如果设置为false,
    回调函数则有与被mocked的函数同样的接口。当你想要使用回调函数来做测试桩时,这个很好用。

    • 默认: true
  • :cexception_include:
    告诉:cexception插件去哪里找“CException.h"。只有当这文件不在你的build路径中时你才需要定义它。

    • 默认: nil
  • :enforce_strict_ordering:
    CMock总是检查你对同一个函数的调用顺序,所以如果你希望GrabNabber(int size)被调用三次,它就会验证
    sizes是按照你指定的顺序传递的。你也许还想确保所有不同的函数间也是按照特定顺序调用的,如果是
    这样的话,把这个设置为true。

    • 默认: false
  • :framework:
    当前唯一的选项就是:unity。以后要是我们支持了其他单元测试框架(或者如果你帮我们写了一个),它们
    将被加到这里

    : 默认: :unity

  • :includes:
    一列应该被加到mocks中的额外的include文件。对于用在你的工程内的全局类型和定义很有用。如果你关心
    这些文件应该被include到mock文件中的某个具体位置的话。你可以在后面的几个选项中选择需要的。

    • :includes
    • :includes_h_pre_orig_header
    • :includes_h_post_orig_header
    • :includes_c_pre_header
    • :includes_c_post_header
    • 默认: nil #对于所有5个选项
  • :memcmp_if_unknown:
    C开发者创造了许多的类型,有的通过typedef,有的通过预处理器宏。CMock不打算自动地知道所有你所想的
    (尽管它尽可能地知道)。如果它遇到了一个它不认识的类型,你可以选择你要想要CMock怎么处理它。它可以
    进行原始的内存比较,然后报告任何差异,或者也可以失败并报告一个有意义的消息。不管哪种方式,这个
    特性只会在所有其他机制都行不通的时候才会用到(遇到的东西不是一个标准类型。它不在:treat_as列表中。
    它不在一个定制的unity_helper中)。

    • 默认: true
  • :mock_path:
    你想要生成的mock文件存放在哪个路径

    • 默认: mocks
  • :mock_prefix:
    你mock文件的前缀。比如,如果是“Mock”,文件“USART.h”的mock文件就会叫做“MockUSART.c”。这可以同时
    跟后缀一起使用

    • 默认: Mock
  • :mock_suffix:
    你mock文件的后缀。比如,如果是“_Mock”,文件“USART.h”的mock文件就会叫做“USART_Mock.c”。这可以同
    时跟前缀一起使用。

    • 默认: “”
  • :plugins:
    一个启用的插件的数组。’:expect’总是启用的。当前还有以下可用插件。

    • :ignore
    • :ignore_arg
    • :expect_any_args
    • :array
    • :cexception
    • :callback
    • :return_thru_ptr
  • :strippables:
    包含了一个项目清单的数组,里头的项目会在决定什么应该被mock前移除出头文件。
    这可以简单的如一个CMock不识别的编译器扩展,或者可以是一个正则表达式以拒绝
    特定的函数名模式。这是当你的测试编译器不支持某编译器扩展时,摆脱其的一个
    很棒的方式。比如,使用:strippables: ['(?:functionName\s*\(+.*?\)+)']
    阻止函数functionName被mocked。默认的,它忽略所有gcc attribute扩展。

    • 默认: [’(?:attribute\s*(+.*?)+)’]
  • :subdir:
    这是你的mock们的一个相对子路径。比如设置这个为"sys"来为sys/types.h
    (:mock_path)/sys/中创建一个mock。

    • 默认: “”
  • :treat_as:
    当你为标准类型使用了typedefs时,:treat_as列表是一条捷径。当unity函数
    TEST_ASSERT_EQUAL_HEX16能够完美工作时为什么还要为UINT16创建一个定制的
    unity helper呢?只要添加’UINT16’ => ‘HEX16’到你的列表中就行(实际上,别
    。我们已经帮你做了这事了)。也许你有一个类型,这个类型是指向一个无符号
    字符型数组的指针?没问题,只用添加’UINT8_T*’ => ‘HEX8*’。

    • 注意:不像其他选项,在这个选项中你指定的东西会合并进默认列表。因此,
      如果你想要重写一些东西,你必须将其重赋值为其他东西(或者为nil如果你
      不想要它)。

    • 默认:

      • ‘int’: ‘INT’
      • ‘char’: ‘INT8’
      • ‘short’: ‘INT16’
      • ‘long’: ‘INT’
      • ‘int8’: ‘INT8’
      • ‘int16’: ‘INT16’
      • ‘int32’: ‘INT’
      • ‘int8_t’: ‘INT8’
      • ‘int16_t’: ‘INT16’
      • ‘int32_t’: ‘INT’
      • ‘INT8_T’: ‘INT8’
      • ‘INT16_T’: ‘INT16’
      • ‘INT32_T’: ‘INT’
      • ‘bool’: ‘INT’
      • ‘bool_t’: ‘INT’
      • ‘BOOL’: ‘INT’
      • ‘BOOL_T’: ‘INT’
      • ‘unsigned int’: ‘HEX32’
      • ‘unsigned long’: ‘HEX32’
      • ‘uint32’: ‘HEX32’
      • ‘uint32_t’: ‘HEX32’
      • ‘UINT32’: ‘HEX32’
      • ‘UINT32_T’: ‘HEX32’
      • ‘void*’: ‘HEX8_ARRAY’
      • ‘unsigned short’: ‘HEX16’
      • ‘uint16’: ‘HEX16’
      • ‘uint16_t’: ‘HEX16’
      • ‘UINT16’: ‘HEX16’
      • ‘UINT16_T’: ‘HEX16’
      • ‘unsigned char’: ‘HEX8’
      • ‘uint8’: ‘HEX8’
      • ‘uint8_t’: ‘HEX8’
      • ‘UINT8’: ‘HEX8’
      • ‘UINT8_T’: ‘HEX8’
      • ‘char*’: ‘STRING’
      • ‘pCHAR’: ‘STRING’
      • ‘cstring’: ‘STRING’
      • ‘CSTRING’: ‘STRING’
      • ‘float’: ‘FLOAT’
      • ‘double’: ‘FLOAT’
  • :treat_as_void:
    我们见过“滑稽的”遗留系统typedef 'void’为一个定制类型,像MY_VOID。把这样
    的实例都加入这个列表中以帮助CMock明白怎么处理你的代码。

    • 默认: []
  • :treat_externs:
    这指明了你想要CMock怎么处理在头文件中被标记为extern的函数。应该mock它们么?

    • :include 将mock externed的函数。
    • :exclude 将忽略externed的函数(默认)。
  • :unity_helper_path:
    如果你创建了一个头文件,里头放着你自己对unity的扩展以帮助处理你自己的
    类型。你可以将这个参数设置到那个路径。CMock之后会自动地pull进你的helpers
    然后使用它们。唯一的窍门是你要确保你遵从命名约定:
    UNITY_TEST_ASSERT_EQUAL_YourType。如果它发现正确形状的宏匹配这个模式,
    它将会使用它们。

    • 默认: []
  • :verbosity:
    CMock应该有多吵?

    • 0 仅仅对于错误
    • 1 错误和警告
    • 2 普通(默认)
    • 3 非常啰嗦
  • :weak:
    当把这个设置为某些值时,生成的mock会被是用配置的格式定义为weak符号。这使得它们
    能够被在特定的测试中覆写。

    • 当使用GCC时设置为 ‘__attribute ((weak))’ 以weak mocks.
    • 当使用IAR时设置为任何非空字符串weak mocks.
    • 默认: “”
  • :when_no_prototypes:
    当你给CMock一个头文件并要求对其创建一个mock,其中通常包含函数原型(否则怎么
    创建?)。你可以控制当其中不包含函数原型时怎么办。可以设置为:warn,
    :ignore,:error

    • 默认: :warn
  • :when_ptr:
    你可以定制想要CMock怎么处理指针(c字符串的结果是字符串比较。我们这里讨论的是
    其他指针)。:compare_ptr则会仅仅验证指针相同,:compare_data:smart
    则会验证数据一样。:compare_data:smart的行为基于你是否启用array插件而
    略有不同。默认的,它们会比较被指向的单个元素。所以如果你有一个指向叫做ORGAN_T
    的结构体的指针,它将会比较一个ORGAN_T(不管是不是一个)。

    • 默认: :smart
  • :fail_on_unexpected_calls:
    默认的,如果在_Expect和_Ignore被先调用之前,一个mock被调用了,CMock将使得一个测试失败。
    尽管这样能强迫测试作者更加准确的描述它们的预期,这也会使的测试中充斥着大量和测试的焦点
    无关的_Expect和_Ignore。尽管这也很好地提醒了用户应该要重构模块了,一些用户却并不喜欢这
    些额外的噪音。

    因此可以将:fail_on_unexpected_calls设置为false以使得所有的mocks一开始默认已使用了_Ignore,
    然后你得使用其他选项来重写它。

    • 默认: true
    • 注意:
      如果这个选项被禁用了,mocked函数当被调用时将返回默认值(0)(当然特指需要返回一些值的情况)

编译选项:

还存在许多可以定制cmock行为的#defines。你可以把以下传入你的编译器或者做其他最方便方式,随便啦。
不然CMock就会尽可能地基于其他设置,特别是Unity的设置,来猜测你想要什么。

  • CMOCK_MEM_STATIC or CMOCK_MEM_DYNAMIC
    定义其中一个以决定你是否想要在测试中动态地从堆中获取内存。如果选择了static,你可以控制Cmock的
    总内存占用。如果选择了dynamic,你将需要确保Cmock能获得足够的堆空间。

  • CMOCK_MEM_SIZE
    在static模式下,这个宏定义了你分配给Cmock的总内存量。在dynamic模式下,这个则是每次分配的内存块
    大小(大数字会多占用空间但好处是更少的mallocs调用)

  • CMOCK_MEM_ALIGN
    你的数据的对齐方式。如大部分嵌入式设计者所知,不是所有东西都像PC那么灵活。这个默认设为2,意思是
    对齐到最接近 2^2 -> 4字节(32位)。设置为0可以关闭对齐,设置为1强迫对齐到最接近uint16或设置为3强迫
    最接近到uint64。

  • CMOCK_MEM_PTR_AS_INT
    这是内部用来保存指针的…这需要足够大。在大部分预处理器中,指针和一个unsigned long一样长…但也许
    对你来说不是这样的呢?

  • CMOCK_MEM_INDEX_TYPE
    这需要足够大以指向Cmock的任意内存空间…通常这是一个unsigned int。

例子

你可以在 examples 路径 下找到许多示例,示范了你可以怎么把CMock用作你build过程的工具。
你也许还考虑使用 Ceedling。请注意,这些示例是想要展示build过程是
怎么工作的。它们会故意使测试失败以展示会发生什么。不用大惊小怪的。 ?


以下为中英对照版


CMock: A Summary

ThrowTheSwitch.org

This documentation is released under a Creative Commons 3.0 Attribution Share-Alike License

What Exactly Are We Talking About Here?

CMock is a nice little tool which takes your header files and creates
a Mock interface for it so that you can more easily unit test modules
that touch other modules. For each function prototype in your
header, like this one:
CMock是一个很棒的小工具,它翻了翻你的头文件,然后为其创建出一个mock接口,这样你就可以很方便的
对依赖于其他模块的模块进行单元测试。对于你的头文件中的每个函数原型,像这个:

int DoesSomething(int a, int b);

…you get an automatically generated DoesSomething function
that you can link to instead of your real DoesSomething function.
By using this Mocked version, you can then verify that it receives
the data you want, and make it return whatever data you desire,
make it throw errors when you want, and more… Create these for
everything your latest real module touches, and you’re suddenly
in a position of power: You can control and verify every detail
of your latest creation.
你会得到一个自动生成的DoesSomething函数,你可以链接其来替代你真正的DoesSomething函数。
通过使用这个Mocked版本,你可以验证它收到了你想要的数据,并使其返回任何你想返回的数据,
或使其抛出异常,以及其他好玩的……为你被测模块依赖的所有东西创建mock,你会发现你如此nb,
掌控一切:你可以控制和验证被测模块的所有细节。

To make that easier, CMock also gives you a bunch of functions
like the ones below, so you can tell that generated DoesSomething
function how to behave for each test:
为了使这更简单,CMock还给你了一堆函数,如下面这样的,这样你就可以告知生成的DoesSomething
函数在每个测试中应该做什么:

void DoesSomething_ExpectAndReturn(int a, int b, int toReturn);
void DoesSomething_ExpectAndThrow(int a, int b, EXCEPTION_T error);
void DoesSomething_StubWithCallback(CMOCK_DoesSomething_CALLBACK YourCallback);
void DoesSomething_IgnoreAndReturn(int toReturn);

You can pile a bunch of these back to back, and it remembers what
you wanted to pass when, like so:
你可以连续调用它们,它会记住你的期望的顺序,像这样:

test_CallsDoesSomething_ShouldDoJustThat(void)
{DoesSomething_ExpectAndReturn(1,2,3);DoesSomething_ExpectAndReturn(4,5,6);DoesSomething_ExpectAndThrow(7,8, STATUS_ERROR_OOPS);CallsDoesSomething( );
}

This test will call CallsDoesSomething, which is the function
we are testing. We are expecting that function to call DoesSomething
three times. The first time, we check to make sure it’s called
as DoesSomething(1, 2) and we’ll magically return a 3. The second
time we check for DoesSomething(4, 5) and we’ll return a 6. The
third time we verify DoesSomething(7, 8) and we’ll throw an error
instead of returning anything. If CallsDoesSomething gets
any of this wrong, it fails the test. It will fail if you didn’t
call DoesSomething enough, or too much, or with the wrong arguments,
or in the wrong order.
这个测试会调用CallsDoesSomething,即我们正在测试的函数。我们期望这函数调用DoesSomething
上次。第一次,我们验证它是按DoesSomething(1, 2)这样调用的,并且返回给其3.第二次,我们验
证它是按DoesSomething(4, 5)这样调用的,并返回给其6.第三次,我们验证它是按
DoesSomething(7, 8)这样调用的,并不返回任何东西直接抛出一个错误。如果CallsDoesSomething
做错了任何事情,测试就会失败。调用DoesSomething次数太少或太多,调用的参数不对或顺序不对
都会导致失败。

CMock is based on Unity, which it uses for all internal testing.
It uses Ruby to do all the main work (versions 2.0.0 and above).
CMock是基于Unity的,它使用Unity实现所有的内部测试。
它使用Ruby来做所有的主要工作(版本 2.0.0 及以上)

Installing

The first thing you need to do to install CMock is to get yourself
a copy of Ruby. If you’re on linux or osx, you probably already
have it. You can prove it by typing the following:
安装CMock的首件事就是获得一份Ruby的副本。如果你用linux或osx,你很可能已经有了。可以通过
在命令行中输入以下东西来验证:

ruby --version

If it replied in a way that implies ignorance, then you’re going to
need to install it. You can go to ruby-lang
to get the latest version. You’re also going to need to do that if it
replied with a version that is older than 2.0.0. Go ahead. We’ll wait.
如果答复显示你没有ruby的话,那你得去安装它了。你可以在ruby-lang
获得最新版本。如果答复显示ruby的版本比2.0.0旧的话,你同样得去升级ruby了。快,我们等你。

Once you have Ruby, you have three options:
一旦你有了Ruby,你有三个选择:

  • Clone the latest CMock repo on github
  • Download the latest CMock zip from github
  • Install Ceedling (which has it built in!) through your commandline using gem install ceedling.
  • 克隆最新版github上的CMock仓储
  • 下载最新版github上的CMock zip
  • 通过在命令行中输入gem install ceedling安装Ceedling(内建了CMock)

Generated Mock Module Summary

In addition to the mocks themselves, CMock will generate the
following functions for use in your tests. The expect functions
are always generated. The other functions are only generated
if those plugins are enabled:
除了mocks自身外,CMock还会生成以下函数以用于你自己的测试中。expect函数总是会生成的。其他函数
则只在启用了对应插件时才会生成。

Expect:

Your basic staple Expects which will be used for most of your day
to day CMock work. By calling this, you are telling CMock that you
expect that function to be called during your test. It also specifies
which arguments you expect it to be called with, and what return
value you want returned when that happens. You can call this function
multiple times back to back in order to queue up multiple calls.
在你使用CMock中最常使用的就是Expect系列函数了。调用它,你就是在告诉CMock你期望在你的测试中
这个函数会被调用。它还指定了你期望它被调用时传递的是哪个参数,以及应该返回哪个值。你可以连续
多次调用这个函数以指定多次调用的顺序。

  • void func(void) => void func_Expect(void)
  • void func(params) => void func_Expect(expected_params)
  • retval func(void) => void func_ExpectAndReturn(retval_to_return)
  • retval func(params) => void func_ExpectAndReturn(expected_params, retval_to_return)

ExpectAnyArgs:

This behaves just like the Expects calls, except that it doesn’t really
care what the arguments are that the mock gets called with. It still counts
the number of times the mock is called and it still handles return values
if there are some.

这个的行为就好像Expect,除了它并不真正关心mock被调用时传递的参数是什么。它仍会计数被调用的次数,
并且如果有返回值的话,仍会处理返回值。

  • void func(void) => void func_ExpectAnyArgs(void)
  • void func(params) => void func_ExpectAnyArgs(void)
  • retval func(void) => void func_ExpectAnyArgsAndReturn(retval_to_return)
  • retval func(params) => void func_ExpectAnyArgsAndReturn(retval_to_return)

Array:

An ExpectWithArray is another variant of Expect. Like expect, it cares about
the number of times a mock is called, the arguments it is called with, and the
values it is to return. This variant has another feature, though. For anything
that resembles a pointer or array, it breaks the argument into TWO arguments.
The first is the original pointer. The second specify the number of elements
it is to verify of that array. If you specify 1, it’ll check one object. If 2,
it’ll assume your pointer is pointing at the first of two elements in an array.
If you specify zero elements, it will check just the pointer if
:smart mode is configured or fail if :compare_data is set.

ExpectWithArray是Expect的另一种变化。跟expect一样,它关心mock被调用的次数,被调用时传递的参数,
以及它要返回什么值。但这个变化有另一个特性。对于任何参数中有指针或者数组的函数,它会把这参数分
为两个参数。第一个是原来的指针。第二个指明数组中要验证的元素的个数。如果你指定了1,它会验证一个
对象。如果指定了2,它会假设你的指针指向一个数组中的头两个元素。如果你指定了0个元素,当配置了
:smart模式,它只会检查指针,当配置了:compare_data,就会直接失败。

  • void func(void) => (nothing. In fact, an additional function is only generated if the params list contains pointers)
  • void func(ptr * param, other) => void func_ExpectWithArray(ptr* param, int param_depth, other)
  • retval func(void) => (nothing. In fact, an additional function is only generated if the params list contains pointers)
  • retval func(other, ptr* param) => void func_ExpectWithArrayAndReturn(other, ptr* param, int param_depth, retval_to_return)

Ignore:

Maybe you don’t care about the number of times a particular function is called or
the actual arguments it is called with. In that case, you want to use Ignore. Ignore
only needs to be called once per test. It will then ignore any further calls to that
particular mock. The IgnoreAndReturn works similarly, except that it has the added
benefit of knowing what to return when that call happens. If the mock is called more
times than IgnoreAndReturn was called, it will keep returning the last value without
complaint. If it’s called less times, it will also ignore that. You SAID you didn’t
care how many times it was called, right?
也许你不关心一个特定函数被调用的次数或被调用时的实参。这种情况下,你会想要使用Ignore。
Ignore在每个测试中只需要调用一次。然后它将忽视之后对那个特定mock的任何调用。IgnoreAndReturn的工作
方式很相似,除了它还知道万一调用发生了,应该返回什么值。如果mock被调用的次数超过了IgnoreAndReturn
被调用的次数,它会不断返回最后一次被调用时指定的那个值,这不会导致失败。如果被调用的次数少了,
也没有任何问题。你就是想要表达你不关心它被调用了多少次,对吧?

  • void func(void) => void func_Ignore(void)
  • void func(params) => void func_Ignore(void)
  • retval func(void) => void func_IgnoreAndReturn(retval_to_return)
  • retval func(params) => void func_IgnoreAndReturn(retval_to_return)

Ignore Arg:

Maybe you overall want to use Expect and its similar variations, but you don’t care
what is passed to a particular argument. This is particularly useful when that argument
is a pointer to a value that is supposed to be filled in by the function. You don’t want
to use ExpectAnyArgs, because you still care about the other arguments. Instead, before
any of your Expect calls are made, you can call this function. It tells CMock to ignore
a particular argument for the rest of this test, for this mock function.
也许你想使用Expect以及它所有的变化,但是你不关心传了什么参数。这在参数是一个指针,指向要由函数来
填充值的位置时特别有用。因为你仍然关心其他参数,你并不想使用ExpectAnyArgs。因此,取而代之的,在
你调用任何expect之前,你可以调用这个函数。它使CMock在接下来的这个测试中忽略这个mock函数的特定参数。

  • void func(params) => void func_IgnoreArg_paramName(void)

ReturnThruPtr:

Another option which operates on a particular argument of a function is the ReturnThruPtr
plugin. For every argument that resembles a pointer or reference, CMock generates an
instance of this function. Just as the AndReturn functions support injecting one or more
return values into a queue, this function lets you specify one or more return values which
are queued up and copied into the space being pointed at each time the mock is called.
另一个操作函数的一个特定参数的选择是ReturnThruPtr插件。对于每个像指针或引用的参数,CMock都会生成
这个函数的一个实例。就如AndReturn函数支持注入一个或多个返回值到一个队列中,这个函数让你指定一个或
多个返回值,返回值们会被队列化并拷贝进一个区域,每次mock被调用时会指向对应空间。

  • void func(param1) => void func_ReturnThruPtr_paramName(val_to_return)
  • => void func_ReturnArrayThruPtr_paramName(cal_to_return, len)
  • => void func_ReturnMemThruPtr_paramName(val_to_return, size)

Callback:

If all those other options don’t work, and you really need to do something custom, you
still have a choice. As soon as you stub a callback in a test, it will call the callback
whenever the mock is encountered and return the retval returned from the callback (if any)
instead of performing the usual expect checks. It can be configured to check the arguments
first (like expects) or just jump directly to the callback.
如果其他选择都不够用,你确实想要定制一些东西,那还有一个杀招。一旦你在一个测试中stub了一个回调函数,
每当mock被调用,他都会去调用回调函数并返回回调函数中返回的值(如果有返回值的话),而不是进行通常的expect
检查。他可以被配置为先检查参数(就像expects一样)或者也可以直接跳到回调函数。

  • void func(void) => void func_StubWithCallback(CMOCK_func_CALLBACK callback)
    where CMOCK_func_CALLBACK looks like: void func(int NumCalls)
  • void func(params) => void func_StubWithCallback(CMOCK_func_CALLBACK callback)
    where CMOCK_func_CALLBACK looks like: void func(params, int NumCalls)
  • retval func(void) => void func_StubWithCallback(CMOCK_func_CALLBACK callback)
    where CMOCK_func_CALLBACK looks like: retval func(int NumCalls)
  • retval func(params) => void func_StubWithCallback(CMOCK_func_CALLBACK callback)
    where CMOCK_func_CALLBACK looks like: retval func(params, int NumCalls)

Cexception:

Finally, if you are using Cexception for error handling, you can use this to throw errors
from inside mocks. Like Expects, it remembers which call was supposed to throw the error,
and it still checks parameters first.
最后,如果你使用Cexception来处理异常,你可以使用它来从内部mocks抛出错误。正如Expect,它会记得应该在
哪次调用抛出错误,并且它仍然会先检查参数。

  • void func(void) => void func_ExpectAndThrow(value_to_throw)
  • void func(params) => void func_ExpectAndThrow(expected_params, value_to_throw)
  • retval func(void) => void func_ExpectAndThrow(value_to_throw)
  • retval func(params) => void func_ExpectAndThrow(expected_params, value_to_throw)

Running CMock

CMock is a Ruby script and class. You can therefore use it directly
from the command line, or include it in your own scripts or rakefiles.
CMock是一个Ruby脚本和类。因此你可以直接从命令行使用它,或者也可以把它包含在自己的脚本或者rakefiles中。

Mocking from the Command Line

After unpacking CMock, you will find cmock.rb in the ‘lib’ directory.
This is the file that you want to run. It takes a list of header files
to be mocked, as well as an optional yaml file for a more detailed
configuration (see config options below).
在解压CMock后,你可以在’lib’路径中找到cmock.rb。
这就是你想要运行的文件。它的参数是你想要mock的多个头文件,以及可选的yaml文件来
进行更细节的配置(详见下方的配置选项)。

For example, this will create three mocks using the configuration
specified in MyConfig.yml:
比如,这样就能使用MyConfig.yml中的配置创建三个mocks。

ruby cmock.rb -oMyConfig.yml super.h duper.h awesome.h

And this will create two mocks using the default configuration:
这将使用默认配置创建两个mock。

ruby cmock.rb ../mocking/stuff/is/fun.h ../try/it/yourself.h

Mocking From Scripts or Rake

CMock can be used directly from your own scripts or from a rakefile.
Start by including cmock.rb, then create an instance of CMock.
When you create your instance, you may initialize it in one of
three ways.
CMock可以从你自己的脚本或从一个rakefile中间接的使用。
先include cmock.rb,然后创建一个CMock的实例。
当你创建了自己的实例,有三种方式可以初始化它。

You may specify nothing, allowing it to run with default settings:
你可以什么都不指定,让它使用默认配置运行:

require 'cmock.rb'
cmock = CMock.new

You may specify a YAML file containing the configuration options
you desire:
你可以指定一个YAML文件,其中包含你想要的配置选项:

cmock = CMock.new('../MyConfig.yml')

You may specify the options explicitly:
你可以明确地指定选项:

cmock = Cmock.new(:plugins => [:cexception, :ignore], :mock_path => 'my/mocks/')

Config Options:

The following configuration options can be specified in the
yaml file or directly when instantiating.
以下配置选项可以指定在yaml文件中,或者在实例化时间接指定。

Passed as Ruby, they look like this:
在Ruby中传参时,看起来像这样。

    { :attributes => [“__funky”, “__intrinsic”], :when_ptr => :compare }

Defined in the yaml file, they look more like this:
定义在yaml文件中时,看起来更像这样。

    :cmock::attributes:- __funky- __intrinsic:when_ptr: :compare

In all cases, you can just include the things that you want to override
from the defaults. We’ve tried to specify what the defaults are below.
所有情况下,你都可以仅包含那些你想要覆盖默认配置的选项。后面我们会试着说明哪些是默认的。

  • :attributes:
    These are attributes that CMock should ignore for you for testing
    purposes. Custom compiler extensions and externs are handy things to
    put here. If your compiler is choking on some extended syntax, this
    is often a good place to look.
    这里指定了CMock为了测试目的,应该忽略掉的属性。定制的编译器扩展以及externs就是要放在这里的东西。
    如果你的编译器因为一些扩展的语法而编译出问题了,你可以来看看这里。

    • defaults: [’__ramfunc’, ‘__irq’, ‘__fiq’, ‘register’, ‘extern’]
    • note: this option will reinsert these attributes onto the mock’s calls.
      If that isn’t what you are looking for, check out :strippables.
      注意 这个选择会在mock的调用中重新插入这些属性。
      如果这不是你想要的,看看:strippables
  • :c_calling_conventions:
    Similarly, CMock may need to understand which C calling conventions
    might show up in your codebase. If it encounters something it doesn’t
    recognize, it’s not going to mock it. We have the most common covered,
    but there are many compilers out there, and therefore many other options.
    类似地,CMock可能需要理解在你的代码中可能会出现哪个C调用约定。如果它遇到了一些它不认识的,
    它不打算mock它。我们已经默认写了一些最常用的,但是还有许多编译器,因此可能有更多选项。

    • defaults: [’__stdcall’, ‘__cdecl’, ‘__fastcall’]
    • note: this option will reinsert these attributes onto the mock’s calls.
      If that isn’t what you are looking for, check out :strippables.
      注意 这个选择会在mock的调用中重新插入这些属性。
      如果这不是你想要的,看看:strippables
  • :callback_after_arg_check:
    Tell :callback plugin to do the normal argument checking before it
    calls the callback function by setting this to true. When false, the
    callback function is called instead of the argument verification.
    通过将这个设置为true来告诉:callback插件在它调用回调函数之前先进行正常的参数检查。
    当设置为false时,就会直接调用回调函数,而不会进行参数验证。

    • default: false
  • :callback_include_count:
    Tell :callback plugin to include an extra parameter to specify the
    number of times the callback has been called. If set to false, the
    callback has the same interface as the mocked function. This can be
    handy when you’re wanting to use callback as a stub.
    要求:callback插件包含一个额外的参数来告知回调函数它已被调用几次了。如果设置为false,
    回调函数则有与被mocked的函数同样的接口。当你想要使用回调函数来做测试桩时,这个很好用。

    • default: true
  • :cexception_include:
    Tell :cexception plugin where to find CException.h… You only need to
    define this if it’s not in your build path already… which it usually
    will be for the purpose of your builds.
    告诉:cexception插件去哪里找“CException.h"。只有当这文件不在你的build路径中时你才需要定义它。

    • default: nil
  • :enforce_strict_ordering:
    CMock always enforces the order that you call a particular function,
    so if you expect GrabNabber(int size) to be called three times, it
    will verify that the sizes are in the order you specified. You might
    also want to make sure that all different functions are called in a
    particular order. If so, set this to true.
    CMock总是检查你对同一个函数的调用顺序,所以如果你希望GrabNabber(int size)被调用三次,它就会验证
    sizes是按照你指定的顺序传递的。你也许还想确保所有不同的函数间也是按照特定顺序调用的,如果是
    这样的话,把这个设置为true。

    • default: false
  • :framework:
    Currently the only option is :unity. Eventually if we support other
    unity test frameworks (or if you write one for us), they’ll get added
    here.
    当前唯一的选项就是:unity。以后要是我们支持了其他单元测试框架(或者如果你帮我们写了一个),它们
    将被加到这里

    : default: :unity

  • :includes:
    An array of additional include files which should be added to the
    mocks. Useful for global types and definitions used in your project.
    There are more specific versions if you care WHERE in the mock files
    the includes get placed. You can define any or all of these options.
    一列应该被加到mocks中的额外的include文件。对于用在你的工程内的全局类型和定义很有用。如果你关心
    这些文件应该被include到mock文件中的某个具体位置的话。你可以在后面的几个选项中选择需要的。

    • :includes
    • :includes_h_pre_orig_header
    • :includes_h_post_orig_header
    • :includes_c_pre_header
    • :includes_c_post_header
    • default: nil #for all 5 options
  • :memcmp_if_unknown:
    C developers create a lot of types, either through typedef or preprocessor
    macros. CMock isn’t going to automatically know what you were thinking all
    the time (though it tries its best). If it comes across a type it doesn’t
    recognize, you have a choice on how you want it to handle it. It can either
    perform a raw memory comparison and report any differences, or it can fail
    with a meaningful message. Either way, this feature will only happen after
    all other mechanisms have failed (The thing encountered isn’t a standard
    type. It isn’t in the :treat_as list. It isn’t in a custom unity_helper).
    C开发者创造了许多的类型,有的通过typedef,有的通过预处理器宏。CMock不打算自动地知道所有你所想的
    (尽管它尽可能地知道)。如果它遇到了一个它不认识的类型,你可以选择你要想要CMock怎么处理它。它可以
    进行原始的内存比较,然后报告任何差异,或者也可以失败并报告一个有意义的消息。不管哪种方式,这个
    特性只会在所有其他机制都行不通的时候才会用到(遇到的东西不是一个标准类型。它不在:treat_as列表中。
    它不在一个定制的unity_helper中)。

    • default: true
  • :mock_path:
    The directory where you would like the mock files generated to be
    placed.
    你想要生成的mock文件存放在哪个路径

    • default: mocks
  • :mock_prefix:
    The prefix to prepend to your mock files. For example, if it’s “Mock”, a file
    “USART.h” will get a mock called “MockUSART.c”. This CAN be used with a suffix
    at the same time.
    你mock文件的前缀。比如,如果是“Mock”,文件“USART.h”的mock文件就会叫做“MockUSART.c”。这可以同时
    跟后缀一起使用

    • default: Mock
  • :mock_suffix:
    The suffix to append to your mock files. For example, it it’s “_Mock”, a file
    “USART.h” will get a mock called “USART_Mock.h”. This CAN be used with a prefix
    at the same time.
    你mock文件的后缀。比如,如果是“_Mock”,文件“USART.h”的mock文件就会叫做“USART_Mock.c”。这可以同
    时跟前缀一起使用。

    • default: “”
  • :plugins:
    An array of which plugins to enable. ‘:expect’ is always active. Also
    available currently:
    一个启用的插件的数组。’:expect’总是启用的。当前还有以下可用插件。

    • :ignore
    • :ignore_arg
    • :expect_any_args
    • :array
    • :cexception
    • :callback
    • :return_thru_ptr
  • :strippables:
    An array containing a list of items to remove from the header
    before deciding what should be mocked. This can be something simple
    like a compiler extension CMock wouldn’t recognize, or could be a
    regex to reject certain function name patterns. This is a great way to
    get rid of compiler extensions when your test compiler doesn’t support
    them. For example, use :strippables: ['(?:functionName\s*\(+.*?\)+)']
    to prevent a function functionName from being mocked. By default, it
    is ignoring all gcc attribute extensions.
    包含了一个项目清单的数组,里头的项目会在决定什么应该被mock前移除出头文件。
    这可以简单的如一个CMock不识别的编译器扩展,或者可以是一个正则表达式以拒绝
    特定的函数名模式。这是当你的测试编译器不支持某编译器扩展时,摆脱其的一个
    很棒的方式。比如,使用:strippables: ['(?:functionName\s*\(+.*?\)+)']
    阻止函数functionName被mocked。默认的,它忽略所有gcc attribute扩展。

    • default: [’(?:attribute\s*(+.*?)+)’]
  • :subdir:
    This is a relative subdirectory for your mocks. Set this to e.g. “sys” in
    order to create a mock for sys/types.h in (:mock_path)/sys/.
    这是你的mock们的一个相对子路径。比如设置这个为"sys"来为sys/types.h
    (:mock_path)/sys/中创建一个mock。

    • default: “”
  • :treat_as:
    The :treat_as list is a shortcut for when you have created typedefs
    of standard types. Why create a custom unity helper for UINT16 when
    the unity function TEST_ASSERT_EQUAL_HEX16 will work just perfectly?
    Just add ‘UINT16’ => ‘HEX16’ to your list (actually, don’t. We already
    did that one for you). Maybe you have a type that is a pointer to an
    array of unsigned characters? No problem, just add ‘UINT8_T*’ =>
    ‘HEX8*’
    当你为标准类型使用了typedefs时,:treat_as列表是一条捷径。当unity函数
    TEST_ASSERT_EQUAL_HEX16能够完美工作时为什么还要为UINT16创建一个定制的
    unity helper呢?只要添加’UINT16’ => ‘HEX16’到你的列表中就行(实际上,别
    。我们已经帮你做了这事了)。也许你有一个类型,这个类型是指向一个无符号
    字符型数组的指针?没问题,只用添加’UINT8_T*’ => ‘HEX8*’。

    • NOTE: unlike the other options, your specifications MERGE with the
      default list. Therefore, if you want to override something, you must
      reassign it to something else (or to nil if you don’t want it)
      注意:不像其他选项,在这个选项中你指定的东西会合并进默认列表。因此,
      如果你想要重写一些东西,你必须将其重赋值为其他东西(或者为nil如果你
      不想要它)。

    • default:

      • ‘int’: ‘INT’
      • ‘char’: ‘INT8’
      • ‘short’: ‘INT16’
      • ‘long’: ‘INT’
      • ‘int8’: ‘INT8’
      • ‘int16’: ‘INT16’
      • ‘int32’: ‘INT’
      • ‘int8_t’: ‘INT8’
      • ‘int16_t’: ‘INT16’
      • ‘int32_t’: ‘INT’
      • ‘INT8_T’: ‘INT8’
      • ‘INT16_T’: ‘INT16’
      • ‘INT32_T’: ‘INT’
      • ‘bool’: ‘INT’
      • ‘bool_t’: ‘INT’
      • ‘BOOL’: ‘INT’
      • ‘BOOL_T’: ‘INT’
      • ‘unsigned int’: ‘HEX32’
      • ‘unsigned long’: ‘HEX32’
      • ‘uint32’: ‘HEX32’
      • ‘uint32_t’: ‘HEX32’
      • ‘UINT32’: ‘HEX32’
      • ‘UINT32_T’: ‘HEX32’
      • ‘void*’: ‘HEX8_ARRAY’
      • ‘unsigned short’: ‘HEX16’
      • ‘uint16’: ‘HEX16’
      • ‘uint16_t’: ‘HEX16’
      • ‘UINT16’: ‘HEX16’
      • ‘UINT16_T’: ‘HEX16’
      • ‘unsigned char’: ‘HEX8’
      • ‘uint8’: ‘HEX8’
      • ‘uint8_t’: ‘HEX8’
      • ‘UINT8’: ‘HEX8’
      • ‘UINT8_T’: ‘HEX8’
      • ‘char*’: ‘STRING’
      • ‘pCHAR’: ‘STRING’
      • ‘cstring’: ‘STRING’
      • ‘CSTRING’: ‘STRING’
      • ‘float’: ‘FLOAT’
      • ‘double’: ‘FLOAT’
  • :treat_as_void:
    We’ve seen “fun” legacy systems typedef ‘void’ with a custom type,
    like MY_VOID. Add any instances of those to this list to help CMock
    understand how to deal with your code.
    我们见过“滑稽的”遗留系统typedef 'void’为一个定制类型,像MY_VOID。把这样
    的实例都加入这个列表中以帮助CMock明白怎么处理你的代码。

    • default: []
  • :treat_externs:
    This specifies how you want CMock to handle functions that have been
    marked as extern in the header file. Should it mock them?
    这指明了你想要CMock怎么处理在头文件中被标记为extern的函数。应该mock它们么?

    • :include will mock externed functions 将mock externed的函数
    • :exclude will ignore externed functions (default). 将忽略externed的函数(默认)
  • :unity_helper_path:
    If you have created a header with your own extensions to unity to
    handle your own types, you can set this argument to that path. CMock
    will then automagically pull in your helpers and use them. The only
    trick is that you make sure you follow the naming convention:
    UNITY_TEST_ASSERT_EQUAL_YourType. If it finds macros of the right
    shape that match that pattern, it’ll use them.
    如果你创建了一个头文件,里头放着你自己对unity的扩展以帮助处理你自己的
    类型。你可以将这个参数设置到那个路径。CMock之后会自动地pull进你的helpers
    然后使用它们。唯一的窍门是你要确保你遵从命名约定:
    UNITY_TEST_ASSERT_EQUAL_YourType。如果它发现正确形状的宏匹配这个模式,
    它将会使用它们。

    • default: []
  • :verbosity:
    How loud should CMock be?
    CMock应该有多吵?

    • 0 for errors only 仅仅对于错误
    • 1 for errors and warnings 错误和警告
    • 2 for normal (default) 普通(默认)
    • 3 for verbose 非常啰嗦
  • :weak:
    When set this to some value, the generated mocks are defined as weak
    symbols using the configured format. This allows them to be overridden
    in particular tests.
    当把这个设置为某些值时,生成的mock会被是用配置的格式定义为weak符号。这使得它们
    能够被在特定的测试中覆写。

    • Set to ‘__attribute ((weak))’ for weak mocks when using GCC.
    • Set to any non-empty string for weak mocks when using IAR.
    • default: “”
  • :when_no_prototypes:
    When you give CMock a header file and ask it to create a mock out of
    it, it usually contains function prototypes (otherwise what was the
    point?). You can control what happens when this isn’t true. You can
    set this to :warn, :ignore, or :error
    当你给CMock一个头文件并要求对其创建一个mock,其中通常包含函数原型(否则怎么
    创建?)。你可以控制当其中不包含函数原型时怎么办。可以设置为:warn,
    :ignore,:error

    • default: :warn
  • :when_ptr:
    You can customize how CMock deals with pointers (c strings result in
    string comparisons… we’re talking about other pointers here). Your
    options are :compare_ptr to just verify the pointers are the same,
    :compare_data or :smart to verify that the data is the same.
    :compare_data and :smart behaviors will change slightly based on
    if you have the array plugin enabled. By default, they compare a
    single element of what is being pointed to. So if you have a pointer
    to a struct called ORGAN_T, it will compare one ORGAN_T (whatever that
    is).
    你可以定制想要CMock怎么处理指针(c字符串的结果是字符串比较。我们这里讨论的是
    其他指针)。:compare_ptr则会仅仅验证指针相同,:compare_data:smart
    则会验证数据一样。:compare_data:smart的行为基于你是否启用array插件而
    略有不同。默认的,它们会比较被指向的单个元素。所以如果你有一个指向叫做ORGAN_T
    的结构体的指针,它将会比较一个ORGAN_T(不管是不是一个)。

    • default: :smart
  • :fail_on_unexpected_calls:
    By default, CMock will fail a test if a mock is called without _Expect and _Ignore
    called first. While this forces test writers to be more explicit in their expectations,
    it can clutter tests with _Expect or _Ignore calls for functions which are not the focus
    of the test. While this is a good indicator that this module should be refactored, some
    users are not fans of the additional noise.
    默认的,如果在_Expect和_Ignore被先调用之前,一个mock被调用了,CMock将使得一个测试失败。
    尽管这样能强迫测试作者更加准确的描述它们的预期,这也会使的测试中充斥着大量和测试的焦点
    无关的_Expect和_Ignore。尽管这也很好地提醒了用户应该要重构模块了,一些用户却并不喜欢这
    些额外的噪音。

    Therefore, :fail_on_unexpected_calls can be set to false to force all mocks to start with
    the assumption that they are operating as _Ignore unless otherwise specified.
    因此可以将:fail_on_unexpected_calls设置为false以使得所有的mocks一开始默认已使用了_Ignore,
    然后你得使用其他选项来重写它。

    • default: true
    • note:
      If this option is disabled, the mocked functions will return
      a default value (0) when called (and only if they have to return something of course).
      如果这个选项被禁用了,mocked函数当被调用时将返回默认值(0)(当然特指需要返回一些值的情况)

Compiled Options:

A number of #defines also exist for customizing the cmock experience.
Feel free to pass these into your compiler or whatever is most
convenient. CMock will otherwise do its best to guess what you want
based on other settings, particularly Unity’s settings.
还存在许多可以定制cmock行为的#defines。你可以把以下传入你的编译器或者做其他最方便方式,随便啦。
不然CMock就会尽可能地基于其他设置,特别是Unity的设置,来猜测你想要什么。

  • CMOCK_MEM_STATIC or CMOCK_MEM_DYNAMIC
    Define one of these to determine if you want to dynamically add
    memory during tests as required from the heap. If static, you
    can control the total footprint of Cmock. If dynamic, you will
    need to make sure you make some heap space available for Cmock.
    定义其中一个以决定你是否想要在测试中动态地从堆中获取内存。如果选择了static,你可以控制Cmock的
    总内存占用。如果选择了dynamic,你将需要确保Cmock能获得足够的堆空间。

  • CMOCK_MEM_SIZE
    In static mode this is the total amount of memory you are allocating
    to Cmock. In Dynamic mode this is the size of each chunk allocated
    at once (larger numbers grab more memory but require less mallocs).
    在static模式下,这个宏定义了你分配给Cmock的总内存量。在dynamic模式下,这个则是每次分配的内存块
    大小(大数字会多占用空间但好处是更少的mallocs调用)

  • CMOCK_MEM_ALIGN
    The way to align your data to. Not everything is as flexible as
    a PC, as most embedded designers know. This defaults to 2, meaning
    align to the closest 2^2 -> 4 bytes (32 bits). You can turn off alignment
    by setting 0, force alignment to the closest uint16 with 1 or even
    to the closest uint64 with 3.
    你的数据的对齐方式。如大部分嵌入式设计者所知,不是所有东西都像PC那么灵活。这个默认设为2,意思是
    对齐到最接近 2^2 -> 4字节(32位)。设置为0可以关闭对齐,设置为1强迫对齐到最接近uint16或设置为3强迫
    最接近到uint64。

  • CMOCK_MEM_PTR_AS_INT
    This is used internally to hold pointers… it needs to be big
    enough. On most processors a pointer is the same as an unsigned
    long… but maybe that’s not true for yours?
    这是内部用来保存指针的…这需要足够大。在大部分预处理器中,指针和一个unsigned long一样长…但也许
    对你来说不是这样的呢?

  • CMOCK_MEM_INDEX_TYPE
    This needs to be something big enough to point anywhere in Cmock’s
    memory space… usually it’s an unsigned int.
    这需要足够大以指向Cmock的任意内存空间…通常这是一个unsigned int。

Examples

You can look in the examples directory for a couple of examples on how
you might tool CMock into your build process. You may also want to consider
using Ceedling. Please note that
these examples are meant to show how the build process works. They have
failing tests ON PURPOSE to show what that would look like. Don’t be alarmed. ?
你可以在 examples 路径 下找到许多示例,示范了你可以怎么把CMock用作你build过程的工具。
你也许还考虑使用 Ceedling。请注意,这些示例是想要展示build过程是
怎么工作的。它们会故意使测试失败以展示会发生什么。不用大惊小怪的。 ?

CMock使用手册翻译相关推荐

  1. TypeScript手册翻译系列4-模块

    为什么80%的码农都做不了架构师?>>>    模块 在TypeScript中利用模块(module)来组织代码.这里将讨论内部和外部模块,以及在何时使用哪种方式更合适,以及怎么使用 ...

  2. tcpprep man 手册翻译

    TCPPREP(1)                                     Programmer's Manual                                   ...

  3. HCPL3120手册翻译

    HCPL3120手册翻译 首先HCPL3120是一个2.5A电流输出的IGBT门极驱动光电耦合器. Description: HCPL3120包含一个磷砷化镓的发光LED,该LED被光电耦合于一个带有 ...

  4. PhysX官方手册翻译

    PhysX官方手册翻译 本人水平有限,翻译中如果出现比较恶的句子...大家一定要查阅原文. 更新:2008-7-1   22:22  Raycasting(射线查询) 更新:2008-6-26 23: ...

  5. netopeer-manager手册翻译

    netopeer-manager(1)手册翻译 名字 netopeer-manager 对netopeer-server的模块管理 概述 netopeer-manager [–help] [ ] 描述 ...

  6. 20050620 GNU Bison 中文手册翻译完成

    20050620 GNU Bison 中文手册翻译完成 GNU Bison实际上是使用最广泛的Yacc-like分析器生成器,使用它可以生成解释器,编译器,协议实现等多种程序. 它不但与Yacc兼容还 ...

  7. awk 4.0+ man手册翻译第一版本

    CentOS 7 上awk 4.0以上版本的man手册翻译第一版: 参考地址:http://www.cnblogs.com/wutao666/p/9732976.html 参考地址:https://w ...

  8. 关于 MATLAB2019 快速入门教程(官方手册翻译)的几点说明

    4月份的两则博文: MATLAB2019 快速入门教程(官方手册翻译)(1/4) MATLAB2019 快速入门教程(官方手册翻译)(2/4) 是写在我尚未找到 MATLAB 中文文档时翻译的,现在我 ...

  9. LLVM language 参考手册 翻译停止相关

    再翻译LLVM language 参考手册的时候,个人感觉很多东西都不是很懂,因此打算学习完编译原理后再去继续研究翻译,多有不便望见谅 转载于:https://www.cnblogs.com/kiri ...

最新文章

  1. Bochs调试及相关仿真工具的使用方法
  2. Algorithm:C++语言实现之图论算法相关(图搜索广度优先BFS、深度优先DFS,最短路径SPF、带负权的最短路径Bellman-ford、拓扑排序)
  3. 如何设计LRU Cache算法
  4. Java代码示例: 使用reflections工具类获取某接口下所有的实现类
  5. ARM指令中STM和LDM的理解误区
  6. Chrome无法播放m3u8格式的直播视频流的问题解决
  7. 树:求二叉树的高度和叶子结点数量
  8. jQuery:实现折叠菜单二级联动动画
  9. fdisk 分区/格式化/挂载
  10. 传说华为面试爱问正则,这不海外留学生校招面试题来了
  11. 从零开始WebAPP尝试(四)----登录实现
  12. Thinkpad Intel 5100无线网卡间歇性掉线问题解决方案
  13. 雷达的主要技术指标、应用与分类和雷达对抗
  14. 四氧化三铁负载石墨烯复合物/氧化石墨烯-四氧化三铁纳米颗粒/稻壳基炭负载纳米四氧化三铁颗粒
  15. 多人共享协作画板——单机画板
  16. JSP标签c:forEach实例
  17. 关于若依框架页面跳转但内容不变的问题
  18. 计算机硬件基础课设总结,计算机硬件基础课程设计报告--简单计算机的设计.doc...
  19. adams将中文改英文
  20. 05Oracle快速入门,docker安装Oracle,springboot整合Oracle

热门文章

  1. MyBatis(一)—— 2h学完这篇就可以入门mybatis啦
  2. Leedcode 875. 爱吃香蕉的珂珂
  3. 首届国际蜂业展在穗举办 零数科技受邀出席
  4. z变换判断稳定性和因果性_信号与系统(奥本海姆)
  5. Python小爬虫之协程爬虫快速上手
  6. P1685 飞跃悬崖
  7. ASP.NET Web API实现简单的文件下载与上传
  8. 牙齿矫正价格降低一半,年轻人距离「牙套自由」还有多远?
  9. kali虚拟机配置成桥接模式
  10. 作为一名Java开发工程师需要掌握哪些专业技能