
root@ubuntu:/home/mf/CUnit-2.1-3# aclocal
aclocal: warning: autoconf input should be named ‘configure.ac’, not ‘configure.in’
root@ubuntu:/home/mf/CUnit-2.1-3# autoconf
root@ubuntu:/home/mf/CUnit-2.1-3# automake
如果在automake过程中有文件丢失,则执行下面命令:automake --add-missing
root@ubuntu:/home/mf/CUnit-2.1-3# chmod u+x configure
root@ubuntu:/home/mf/CUnit-2.1-3#./configure --prefix=$HOME/local
(./configure --prefix 后面加路径可以需要你输入要安装的目录,目录的格式举例如下:/local
这里我是直接./configure,默认路径)
root@ubuntu:/home/mf/CUnit-2.1-3#make
root@ubuntu:/home/mf/CUnit-2.1-3#make install
(到这里位置,我们的cunit的源码库就安装好啦)
这里我准备了4个文件:Main.c test.c testcase.c Makefile
放在Linux 下面新建的 root@ubuntu:/home/mf/Desktop/cunittest目录下

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "Basic.h"
extern void AddTests(void);
int main(int argc, char* argv[])
{
CU_BasicRunMode mode = CU_BRM_VERBOSE;
CU_ErrorAction error_action = CUEA_IGNORE;
int i;
//标准库输出 无缓冲:不使用缓冲。每个 I/O 操作都被即时写入。buffer 和 size 参数被忽略。
setvbuf(stdout, NULL, _IONBF, 0);
for (i=1 ; i<argc ; i++) {
if (!strcmp("-i", *argv)) {
//错误发生时继续执行(默认)
error_action = CUEA_IGNORE;
}
else if (!strcmp("-f", *argv)) {
//错误发生时应系统停止
error_action = CUEA_FAIL;
}
else if (!strcmp("-A", *argv)) {
//错误发生时系统应退出(EXIT)
error_action = CUEA_ABORT;
}
else if (!strcmp("-s", *argv)) {
//只会输出错误信息
mode = CU_BRM_SILENT;
}
else if (!strcmp("-n", *argv)) {
//结果会输出基本信息,包括失败以及测试运行的总体状况
mode = CU_BRM_NORMAL;
}
else if (!strcmp("-v", *argv)) {
//输出测试运行的详细信息
mode = CU_BRM_VERBOSE;
}
else if (!strcmp("-e",*argv)) {
return 0;
}
else {
printf("\nUsage:BasicTest [options]\n\n"
"Options:-i ignore framework errors [default].\n"
" -f fail on framework error.\n"
" -A abort on framework error.\n\n"
" -s silent mode - no output to screen.\n"
" -n normal mode - standard output to screen.\n"
" -v verbose mode - max output to screen [default].\n\n"
" -e print expected test results and exit.\n"
" -h print this message and exit.\n\n");
return 0;
}
}
//CU_initialize_registry registry初始化//用户在调用任何其他CUnit函数之前调用本函数,如果不这样做可能会导致系统崩溃。
if (CU_initialize_registry()) {
printf("\nInitialization of Test Registry failed.");
}
else {
AddTests();
//CU_basic_set_mode()设置运行模式
CU_basic_set_mode(mode);
//CU_set_error_action设置错误发生时,系统的行为
CU_set_error_action(error_action);
//CU_basic_run_tests 运行Tests Basic Mode 基本扩展编程方式 非交互式
printf("\nTests completed with return value %d.\n",CU_basic_run_tests());
// registry释放
CU_cleanup_registry();
}
return 0;
}
/**
*file:test.c
**/
int maxi(int i,int j)
{
return i>j?i:j;
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <CUnit/CUnit.h>
#include <CUnit/Automated.h>
#include <CUnit/TestDB.h>
/**//*---- functions to be tested ------*/
extern int maxi(int i , int j);
/**//*---- test cases ------------------*/
void testIQJ(void)
{
//断言相等比较
CU_ASSERT_EQUAL(maxi(1,1),1);
CU_ASSERT_EQUAL(maxi(0,-0),0);
}
void testIGJ(void)
{
CU_ASSERT_EQUAL(maxi(2,1),2);
CU_ASSERT_EQUAL(maxi(0,-1),0);
CU_ASSERT_EQUAL(maxi(-1,-2),-1);
}
void testILJ(void)
{
CU_ASSERT_EQUAL(maxi(1,2),2);
CU_ASSERT_EQUAL(maxi(-1,0),0);
CU_ASSERT_EQUAL(maxi(-2,-1),-1);
}
CU_TestInfo testcases[] = {
{"Testing i equals j:",testIQJ},
{"Testing i greater than j:",testIGJ},
{"Testing i less than j:", testILJ},
CU_TEST_INFO_NULL
};
/**//*---- test suites ------------------*/
int suite_success_init(void)
{ return 0; }
int suite_success_clean(void)
{ return 0; }
//需要运行的test case
CU_SuiteInfo suites[] = {
{"Testing the function maxi:",suite_success_init,suite_success_clean, NULL, NULL,testcases},
CU_SUITE_INFO_NULL
};
/*cunit运行环境设置*/
void AddTests(void)
{
//1.CU_get_registry CU_register_suites其他一些关于注册的内部函数,主要用于内部和测试的目的
assert(NULL != CU_get_registry());
assert(!CU_is_test_running());
//注册suites
if(CUE_SUCCESS != CU_register_suites(suites)){
fprintf(stderr, "Register suites failed - %s ", CU_get_error_msg());
exit(EXIT_FAILURE);
}
}
INC=-I/usr/local/include/CUnit
LIB=-L/usr/local/lib
all:Main.c test.c testcase.c
gcc -o test $(INC) $(LIB) $^ -lcunit
clean:
-rm -rf *.o test
Makefile文件说明:
(1)INC=填写的是cuint的头文件的目录
(2)LIB=填写的是cunit的lib库的目录
(3)编译命令连接到头文件和lib库 生成可执行文件test
gcc -o test $(INC) $(LIB) $^ -lcunit
root@ubuntu:/home/mf/Desktop/cunittest# make
此时出现了如下错误:没有找到lib库

解决如下:
(1)进入lib库的地址查看,cunit的lib库确实安装没有问题
(2)发现没有动态链接, 还需要设置动态库所在的位置
添加设置一个环境变量: export LD_LIBRARY_PATH=/usr/local/lib,操作如下:
- 打开profile文件添加环境变量
root@ubuntu:/etc# gedit /root/.profile
- 添加好后记得 source /root/.profile
- 修改完毕后,再次执行make,生成一个可执行文件,test
root@ubuntu:/home/mf/Desktop/cunittest# ./test
出现如下报错:

这里的段错误,程序内存出了问题,使用gdb方式进行调试,步骤如下:
- 默认coredump不会保存在磁盘上,需要执ulimit -c unlimited才可以
root@ubuntu:/home/mf/Desktop/cunittest# ulimit -c unlimited- 然后要 指定一下coredump的路径和格式:
root@ubuntu:/home/mf/Desktop/cunittest#echo “/tmp/core-%e-%p” > /proc/sys/kernel/core_pattern- 重新make,在执行./test后就会产生一个coredump了
- 进入coredump文件的目录
- 开启gdb调试
root@ubuntu:/tmp#gdb test.o /tmp/core-test-104138
这里显示导致错误的是signal SIGSEGV信号,一般都是数组越界、死循环或者对空容器进行某些操作导致的。这里想到程序编译的时候出现的警告信息,
继续(gdb) bt 可以看到是CU_register_suites(suites)这个函数出了问题,
函数本身应该没有错误,可能是传给他从参数 有问题,就是那个suites,该参数构建的代码如下:
CU_SuiteInfo suites[] = {
{"testSuite1", suite_success_init, suite_success_clean, testcase },
CU_SUITE_INFO_NULL
};
这个CU_SuiteInfo的数组没有构建正确,该结构有6个成员,但我们定义的时候只有4个成员,直接修改为(以上提供的testcase.c脚本代码已经是修改后正确的代码)
CU_SuiteInfo suites[] = {
{"testSuite1", suite_success_init, suite_success_clean,NULL, NULL, testcase },
CU_SUITE_INFO_NULL
};

很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r
我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain
只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您