Mock的基本概念和方法(续)
来源:互联网 发布:软件系统项目实施方案 编辑:程序博客网 时间:2024/04/25 13:12
本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一@小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!
Content
0. 序
1. 平台
2. 第三方库
3.如何使用CMock和Unity?
3.1 修改业务代码
3.2 编写单元测试
3.3如何Mock并测试?
(1)生成mock文件
(2)生成单元测试runner
(3)拷贝或修改生成的mock文件
(4) build
(5) 讨论
4. 总结
Reference
Appendix 1: Cmock installation
Appendix 2: Unity installation
Appendix 3: Ruby installation
Appendix 4: Mockyour_file.c
Appendix 5: my_business_runner.c
0.序
在Mock的基本概念和方法一文中,笔者在结尾提出了一个问题,有没有一种比较好的方法或者工具,能自动产生一些文件或者目录,供测试使用?
有,一定有,因为,这个世界从来不缺聪明的发明人。
那么,本文仍以Mock的基本概念和方法一文中的例子为例,重点讲述使用Cmock、Unity等工具进行单元测试的方法。
注:本文的实验,CUnit不是必须的。
1.平台
Cygwin, or Linux
工作目录:
Linux : # cd /usr/src/cmock_sample
Cygwin: $ cd /usr/src/cmock_sample
2.第三方库
本文实验用到的第三方库分别为:
cmock_2_0_204.zip:http://sourceforge.net/projects/cmock/files/cmock/cmock2.0/cmock_2_0_204.zip
unity_2_0_113.zip:http://sourceforge.net/projects/unity/files/unity/unity2.0/unity_2_0_113.zip
ruby-1.9-stable.tar.gz:http://ftp.ruby-lang.org/pub/ruby/ruby-1.9-stable.tar.gz
实际上,cmock_2_0_204.zip在其vendor目录中包含了Unity。
3.如何使用CMock和Unity?
以下将以cygwin平台为例。
3.1修改业务代码
该例子中的业务代码文件:my_business.c
为例使用CMock和Unity工具,需要修改my_business.c文件,将其中的main函数删除,并增加my_business.h文件。如下。
/*
* my bussiness.h
*/
int read_file();
my_business.c文件内容。
/*
* my bussiness
*/
#include "my_business.h"
#include
int read_file()
{
FILE* fp = your_file_open("data.txt");
//assert(fp != 0);
/*
* here my business start, for example, read data from the file.
* for test, only print the fp.
*/
printf("%s, %d: file handle = 0x%x/n", __FUNCTION__, __LINE__, (unsigned int)fp);
your_file_close(fp);
return 0;
}
注:实际上,或许某些场合不需要该头文件,但为了本文说明问题的需要,提供该文件。后面的Unity工具将根据该文件自动生成mock文件。
3.2编写单元测试
要对业务代码做单元测试,应该事先编写好单元测试代码,文件为my_business_unittest.c,如下。
/*
* my bussiness unittest
*/
#include "my_business.h"
#include "unity.h"
void setUp(void)
{
}
void tearDown(void)
{
}
void test_read_file()
{
TEST_ASSERT_EQUAL(0, read_file());
}
void test_read_file2()
{
TEST_ASSERT_NOT_EQUAL(1, read_file());
}
3.3如何Mock并测试?
(1)生成mock文件
业务代码my_business.h/.c依赖your_file.h/.c,根据Cmock/Unity框架,要根据your_file.h自动生成mock文件。Cmock框架提供了该自动生成的功能,是用ruby写的scripts,在./cmock/lib目录下,在运行这些脚本时,使用ruby命令,因此需要第三方库ruby。完成该自动生成功能的脚本是./cmock/lib/cmock.rb,可以处理1个或多个.h文件。
$ mkdir mocks //默认情况下,生成的mock文件保存在该目录,故需事先建立好
$ ruby /usr/src/cmock/lib/cmock.rb your_file.h //运行该脚本生成mock文件
Creating mock for your_file...
$ cd mocks
$ ls
Mockyour_file.c Mockyour_file.h //自动生成的mock文件
$ cd ..
此处,笔者仅提供Mockyour_file.h的内容,Mockyour_file.c文件太大,请参考附录。
/* AUTOGENERATED FILE. DO NOT EDIT. */
#ifndef _MOCKYOUR_FILE_H
#define _MOCKYOUR_FILE_H
#include "your_file.h"
void Mockyour_file_Init(void);
void Mockyour_file_Destroy(void);
void Mockyour_file_Verify(void);
#define your_file_open_ExpectAndReturn(fname, cmock_retval) your_file_open_CMockExpectAndReturn(__LINE__, fname, cmock_retval)
void your_file_open_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, char* fname, FILE* cmock_to_return);
#define your_file_close_Expect(fp) your_file_close_CMockExpect(__LINE__, fp)
void your_file_close_CMockExpect(UNITY_LINE_TYPE cmock_line, FILE* fp);
#endif
(2)生成单元测试runner
Unity工具提供了根据单元测试文件自动生成runner文件的功能,该runner文件中包含main()函数,这就是单元测试程序启动的入口。这也是为什么要修改my_business.c,将其中的main()删除的原因。
What a great idea!Ruby真的是一门很好的语言,是时候学习了。
这将节省开发人员很多的时间,使开发人员将精力集中在单元测试本身和设计测试用例上。
$ ruby /usr/src/unity/auto/generate_test_runner.rb my_business_unittest.c my_business_runner.c
$ ls
data.txt makefile my_business.c my_business_runner.c your_file.c
make.bat mocks my_business.h my_business_unittest.c your_file.h
(3)拷贝或修改生成的mock文件
因为生成的mock文件放在mocks目录,且在Mockyour_file.h中包含了your_file.h,但mocks目录中并没有your_file.h文件,而是在上一级目录中,因此需要将其拷贝到上一级目录,或者修改Mockyour_file.h文件中包含your_file.h的路径。笔者选择拷贝。
$ cp mocks/Mockyour_file.h Mockyour_file.h
$ cp mocks/Mockyour_file.c Mockyour_file.c
自此,要进行单元测试所需的.h/.c文件全部建立,小结一下,看看有哪些文件。
你的代码文件:your_file.h/.c (该文件在测试时不再使用)
mocked文件:Mockyour_file.h/.c (在测试时要依赖该文件)
业务代码文件:my_business.h/.c
业务测试文件:my_business_unittest.c
测试运行文件:my_business_runner.c (main()函数即在其中)
(4)build
本文的实验,笔者编写了makefile(Linux平台/Cygwin环境)或者make.bat(win32平台),让build更加快速和可控。
使用CMokc和Unity进行单元测试和Mock,一定会依赖CMock和Unity,因此这两个工具的源代码cmock.c和unity.c也一定要编译到并链接到目标文件。那么对于CMock和Unity,我们需要或者依赖哪些文件呢?
不要被CMock和Unity的内容吓到!虽然其中有很多目录和文件,但其核心(框架)文件很少,而这些核心文件正是build需要的。
CMock: ./cmock/src/cmock.c //CMock的core文件在./cmock/src目录
./cmock/src/cmock.h
Unity: ./unity/src/unity.c //Unity的core文件在./unity/src目录
./unity/src/unity.h
./unity/src/unity_internals.h
综上,编写的makefile文件和make.bat文件如下。makefile文件适用于cygwin和Linux平台。
CXX = gcc
CXXFLAGS += -g -Wall -Wextra
TESTS = my_business
CMOCK_DIR = /usr/src/cmock
CMOCK_SRC = $(CMOCK_DIR)/src
UNITY_DIR = /usr/src/unity
UNITY_SRC = $(UNITY_DIR)/src
ifeq ($(OS), Windows_NT)
TARGET_EXTENSION=.exe
else
TARGET_EXTENSION=.out
endif
TARGET = $(TESTS)$(TARGET_EXTENSION)
CLEANUP = rm -f $(TARGET) *.o
all : $(TARGET)
clean :
$(CLEANUP)
unity.o: $(UNITY_SRC)/unity.c
$(CXX) $(CXXFLAGS) -I$(UNITY_SRC) -c $^
cmock.o: $(CMOCK_SRC)/cmock.c
$(CXX) $(CXXFLAGS) -I$(CMOCK_SRC) -I$(UNITY_SRC) -c $^
mockyour_file.o: mockyour_file.c
$(CXX) $(CXXFLAGS) -I$(CMOCK_SRC) -I$(UNITY_SRC) -c $^
my_business.o: my_business.c
$(CXX) $(CXXFLAGS) -c $^
my_business_unittest.o: my_business_unittest.c
$(CXX) $(CXXFLAGS) -I$(UNITY_SRC) -c $^
my_business_runner.o: my_business_runner.c
$(CXX) $(CXXFLAGS) -I$(UNITY_SRC) -c $^
$(TARGET): unity.o cmock.o mockyour_file.o my_business.o my_business_unittest.o my_business_runner.o
$(CXX) $(CXXFLAGS) $^ -o $@
(5)讨论
这真的是一种前无古人的方法,CMock能自动生成mock文件,让你进行单元测试;Unity能自动生成单元测试runner,让你的单元测试跑起来。CMock和Unity的出现,为广大开发者节省了宝贵的时间,使你的精力集中于单元测试本身和测试用例的设计上。
4.总结
本文,笔者以一个例子讨论了使用CMock和Unity进行mock和单元测试的方法和过程,主要关注如何使用这两个工具并build,build时,要注意CMock和Unity的cmock.c和unity.c也要编译并链接到目标文件。
本文重点如下。
- 生成mock文件
- 生成单元测试runner
- build
广大软件开发者们,如果要做C项目的单元测试,尤其是嵌入式软件的单元测试,那就去大胆尝试CMock和Unity吧!
Reference
CMock简介:CMock Summary.pdf
Unity简介:Unity Summary.pdf
CMock设计原理:Functionality_and_Design_of_the_CMock_Framework.pdf
如何mocking嵌入式软件:Mocking the Embedded World - Test-Driven Development, Continuous Integration, and Design Patterns.pdf
http://sourceforge.net/apps/trac/cmock
http://sourceforge.net/apps/trac/unity
http://sourceforge.net/projects/unity/forums/forum/770030/topic/4067272
http://sourceforge.net/projects/unity/forums/forum/770030/topic/3795145
http://sourceforge.net/apps/trac/cmock/wiki/EclipseIde
http://sourceforge.net/apps/mediawiki/unity/index.php?title=Eclipse_IDE_Integration
http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks (各种单元测试工具比较)
http://sourceforge.net/projects/unity/forums/forum/770030/topic/4067272 (Cmock和Unity的关系)
http://meekrosoft.wordpress.com/2010/01/29/unit-test-embedded-software-in-3-easy-steps (嵌入式软件单元测试的3个步骤)
http://www.lulu.com/product/paperback/embedded-testing-with-unity-and-cmock/14408590?productTrackingContext=search_results/search_shelf/center/1, By Mark VanderVoord.
Appendix 1: Cmock installation
# cd /usr/src
# wget http://sourceforge.net/projects/cmock/files/cmock/cmock2.0/cmock_2_0_204.zip
# unzip -x cmock_2_0_204.zip
# cd cmock
编译需要ruby的构建系统rake,有待研究。
Appendix 2: Unity installation
# cd /usr/src
# wget http://sourceforge.net/projects/unity/files/unity/unity2.0/unity_2_0_113.zip
# unzip -x unity_2_0_113.zip
# cd unity
# make
# cd examples
# make
Appendix 3: Ruby installation
$ cd /usr/src
$ wget http://ftp.ruby-lang.org/pub/ruby/ruby-1.9-stable.tar.gz
$ tar.exe -zxvf ruby-1.9-stable.tar.gz
$ cd ruby-1.9.2-p180
$ ./configure && make && make install
Appendix 4: Mockyour_file.c
Appendix 5: my_business_runner.c
Technorati 标签: 单元测试;Mock;CMock;Unity
- Mock的基本概念和方法(续)
- Mock的基本概念和方法
- 如何写Fake和Mock的方法
- 单元测试和Mock方法
- 单元测试的mock和stub
- Stub和Mock的区别
- Mock和injectMocks的区别
- mock和fake的区别
- Mock和injectMocks的区别
- mock和fake的区别
- JMockit Mock 私有方法和私有属性
- 软件测试的基本概念和方法 [转]
- 查找的基本概念和简单方法
- PageRank的基本概念和幂迭代方法
- 字典的基本概念和常用方法
- Java的基本概念-方法和变量
- HTTP协议的基本概念和方法
- 5、进程通信的基本概念和方法
- 终止线程的运行
- stack unwinding
- extern 的用法
- CxImage类库使用说明(转载)
- CxImage使用心得
- Mock的基本概念和方法(续)
- Android的TabActivity显示不正常(TabWidget)
- Apache Axis2 1.5.4在eclipse环境下的插件安装补充
- 有关.net的web方面的信息
- iframe SECURITY Attribute
- Cpp深入:引用类型
- 中英文职位对照表
- Linux系统调用--semop函数详解
- 亲自编译eucalyputs源码包