《测试驱动的嵌入式C语言开发》—— Unity工具篇之CMOCK

  • CMOCK介绍

CMock从常规Ç头生成纯Ç代码,无需特殊标记。使用CMock指定您希望调用的测试函数以及您希望调用它们的参数。如果某些函数调用对于此测试并不重要,请告诉CMock忽略对它们的调用或者忽略详细信息。有时您想要更多地控制局面,没问题,告诉CMock调用您自己的自定义函数来做任何需要做的事情.CMock处理所有内置类型,只需要一点帮助,它就可以处理任何自定义类型.CMock从简单的标题中自动生成模拟模块,从而避免繁琐地创建自己的存根。

  • CMock如何工作

CMock可以自动为Ç生成模拟和存根。它对基于交互的单元测试很有用,您可以在其中测试一个模块如何与其他模块交互.CMock不是试图将所有这些真实单元编译在一起,而是通过创建所有“其他” 模块的模拟对象来帮助您。然后,您可以使用这些模拟对象来验证您的模块是否正常工作!

CMock使用的Ruby脚本自动生成符合ç头文件中指定的接口的Ç源码块它会在头文件中搜索函数声明例如,您可以告诉它查看您的NeatStuff.h文件,它看到以下内容。:

ARGS* ParseStuff(char* Cmd);
void HandleNeatFeatures(NEAT_FEATURE_T NeatFeature);

CMock接受这些函数声明,并创建一组模拟对象和助手(放在一个名为MockNeatStuff.c和MockNeatStuff.h的新Ç和头文件中):

intParseStuff(char* Cmd);
void ParseStuff_ExpectAndReturn(char* Cmd, int toReturn);
void ParseStuff_IgnoreAndReturn(int toReturn);
void ParseStuff_StubAndCallback(CMOCK_ParseStuff_CALLBACK Callback);

void HandleNeatFeatures(NEAT_FEATURE_T* NeatFeature);
void HandleNeatFeatures_Expect(NEAT_FEATURE_T* NeatFeature);
void HandleNeatFeatures_ExpectWithArrays(NEAT_FEATURE_T* NeatFeature, int NeatFeature_Depth);
void HandleNeatFeatures_Ignore(void);
void HandleNeatFeatures_StubAndCallback(CMOCK_HandleNeatFeatures_CALLBACK Callback);

既然您有这些新功能,您用它们做什么您可以使用它来帮助为NeatStuff.h中调用函数的模块编写测试例如,下面这个例子?:

int MyFunc(char* Command)
{
  int ID;
  NEAT_FEATURES_T Neat;
 
  ID = ParseStuff(Command);
  switch(ID) 
  {
  case 0: 
    HandleStupidFeatures();
    return 1;

  case 1:
    Neat.id = 1;
    Neat.cmd = Command;
    HandleNeatFeatures(Neat);
    return 1;

  default:
    return 0;
  }
}

那么,这是如何工作的?我们如何使用新的嘲笑版本编写测试?好吧,你写了一个看似正常的统一测试。在调用被测函数之前,您可以调用一个或多个期望值。这些说明了你期望被调用的模拟函数。您甚至可以指定您希望看到的参数,并告诉他们要返回哪些数据。后一个功能对于将数据注入函数以验证它们是否能正确处理它非常有用。它看起来像这样:

void test_MyFunc_should_ParseStuffAndCallTheHandlerForNeatFeatures(void)
{
  int retval;

  //We start by saying what our expectations are, and what we want to return
  NEAT_FEATURES_T ExpectedFeatures = { 1, "NeatStuff" };
  ParseStuff_ExpectAndReturn("NeatStuff", 1);
  HandleNeatFeatures_Expect(ExpectedFeatures);

  //Run Actual Function Under Test
  retval = MyFunc("NeatStuff");

  //We can still verify whatever things we normally would after
  TEST_ASSERT_EQUAL(1, retval);
}

 在这种情况下,我们的小测试通过。如果我们在调用ParseStuff_ExpectAndReturn时返回0作为我们的ID,我们将能够验证是否调用了HandleStupidFeatures。每当CMock遇到所谓的与预期不匹配时,它会给我们一个有用的团结失败,例如:

MyFunc.c:23:test_MyFunc_should_ParseStuffAndCallHandler2:FAIL:Function 'HandleStupidFeatures' called less times than expected.

要么:

MyFunc.c:23:test_MyFunc_should_DoOtherStuff:FAIL:Function 'ParseStuff' Argument 'Cmd' Expected 'NeatStuff' was 'DumbStuff'

最好的部分是,所有的管道都是在你几乎不费力的情况下安装的。您只需将CMock指向与您的模块交互的模块的头文件!显然,这将为构建系统带来更多的工作,但是一旦构建系统就位,您就能够快速有效地进行交互测试!

总的而言,CMock是用来快速生成仿真模型,让您可以专心的测试您的代码而无需过多的花费精力在创建仿真模型上,这将大大加速您的测试过程。

 

你可能感兴趣的:(TDD)