单元测试其实非常重要,是软件质量中很重要的部分。单元测试可以保证你的模块的稳定性,提前预知错误。目前的我们的开发中,常常只有集成测试和系统测试,代码可能遗留大量的细小的无法测试出来的错误,这些错误还会互相影响,当BUG真正暴露出来的时候就很难调试,后期测试和维护成本的成本就很高。单元测试把这些容易出错的复杂的地方从繁杂冗长的代码中单独剥离出来了,防止了问题的扩散,针对性的进行测试,能非常迅速的把隐藏在其中的问题明显的暴漏出来。其实解决问题不是难事,难就难在找到问题所在,单元测试就是做这个的。可以说,进行充分的单元测试,是提高软件质量,降低开发成本的必经之路。
单元测试是由开发者自己来写的,是对代码的最小单元进行覆盖测试。要进行充分的单元测试,程序猿要专门编写测试代码,并与产品代码隔离。比较简单的办法是为产品工程建立对应的测试工程,为每个类建立对应的测试类,为每个函数(很简单的除外)建立测试函数。执行单元测试,就是为了证明这段代码的行为和我们期望的一致。所以,测试函数要构造不同的边界条件、用例来覆盖,以验证是否在所有情况下代码的行为都和我们的期望一致。
关于单元测试框架,许多软件巨头都有相应的框架。目前有很多成熟的单元测试框架,比如google有GoogleTest,微软有集成在vs的UnitTestFramework,Qt有Qt的单元测试框架,其他有名的单元测试框架,如CppUnit,JUnit,UnitTest等。这里用Qt的单元测试框架做个简单的演示。
1.首先在qtcreator中新建一个Qt单元测试工程,如图:
2.然后新建一个要被测试的类,里面有将要被测试的Add方法。
【MyModule.h】
#ifndef MYMODULE_H #define MYMODULE_H class MyModule { public: MyModule(); private: int Add(int a, int b); }; #endif // MYMODULE_H
【MyModule.cpp】
#include "mymodule.h" MyModule::MyModule() { } int MyModule::Add(int a, int b) { return a + b; }
然后是测试代码:
【UnitTest.cpp】
#include <QString> #include <QtTest>
//把私有和保护的成员在测试代码中暂时公开 #define private public #define protected public #include "mymodule.h" #undef protected #undef private class UnitTestTest : public QObject { Q_OBJECT public: UnitTestTest(); private Q_SLOTS: void testCase1(); }; UnitTestTest::UnitTestTest() { }
//测试case1 void UnitTestTest::testCase1() { MyModule myModule; QCOMPARE(myModule.Add(1, 1), 2); //比较是否和预料中的结果一致 } QTEST_APPLESS_MAIN(UnitTestTest) #include "tst_unittesttest.moc"
这样,一个简单的测试case就写出来了。当你修改了Add方法,就可以运行单元测试代码来检查是否能达到预期的结果了。
实际要做好单元测试,测试case非常重要。在实际项目中,需要考虑很多,也需要参照一些接口测试的方法,我的总结如下图:
当有完善的单元测试后,以后对旧代码进行修改时,就可以很方便地进行回归测试,以确认修改没有引入新的错误或导致其他代码产生错误。当这样一整套机制建立起来的时候,软件的质量会有很大的提升。