詳解C++ Server測試過程
做好C++ Server測試也是進(jìn)行C++開發(fā)過程中的重要步驟,本文將從開發(fā)階段、白盒測試階段、內(nèi)存測試階段等幾個(gè)方面開始討論。
在C++的世界里,程序設(shè)計(jì)的優(yōu)雅讓位于程序的穩(wěn)定性、健壯性?!昂贸绦蚴菧y出來的”這句話在C++領(lǐng)域里得到了充分體現(xiàn)。下面是我在開發(fā)中使用的測試方法,拋磚引玉,和大家交流下。
C++ Server測試期間,關(guān)閉對core文件的限制,使用命令:ulimit -c unlimited
(1)開發(fā)階段
使用cppunit維護(hù)測試用例。我一般是用于測試解析類、算法類。
從http://sourceforge.net/projects/cppunit/下載最新版本,解壓,看安裝文檔,一般是./configure & make & make install。
下面舉例說明我使用cppunit的方法。假設(shè)自己的源碼位于src目錄下,里面有class1.h/class1.cpp/class2.h/class2.cpp。相對src建立平級目錄test存放測試工程,為class1/class2分別建立測試類文件testClass1.h/testClass2.h,建立main函數(shù)所在文件test.cpp、makefile。
testClass1.h代碼如下,testClass2.h類似。
- #include "class1.h"
- #include
- #include "cppunit/TestRunner.h"
- #include "cppunit/TestResult.h"
- #include "cppunit/TestResultCollector.h"
- #include "cppunit/extensions/HelperMacros.h"
- #include "cppunit/BriefTestProgressListener.h"
- #include "cppunit/extensions/TestFactoryRegistry.h"
- #include "cppunit/TextOutputter.h"
- #include "cppunit/CompilerOutputter.h"
- #include "cppunit/TestCaller.h"
- class testClass1:public CPPUNIT_NS::TestFixture
- {
- CPPUNIT_TEST_SUITE(testClass1);
- CPPUNIT_TEST(testCase1);
- CPPUNIT_TEST(testCase2);
- CPPUNIT_TEST_SUITE_END();
- public:
- virtual void setUp(){}
- virtual void tearDown(){}
- void testCase1()
- {
- testClass1 a;
- a.oper..;
- CPPUNIT_ASSERT_EQAL(a.get..,);
- }
- void testCase2()
- {
- CPPUNIT_ASSERT(==);
- }
- }
test.cpp代碼如下:
- #include "testClass1.h"
- #include "testClass2.h"
- #include
- #include "cppunit/TestRunner.h"
- #include "cppunit/TestResult.h"
- #include "cppunit/TestResultCollector.h"
- #include "cppunit/extensions/HelperMacros.h"
- #include "cppunit/BriefTestProgressListener.h"
- #include "cppunit/extensions/TestFactoryRegistry.h"
- #include "cppunit/TextOutputter.h"
- #include "cppunit/CompilerOutputter.h"
- #include "cppunit/TestCaller.h"
- CPPUNIT_TEST_SUITE_REGISTRATION(testClass1);
- CPPUNIT_TEST_SUITE_REGISTRATION(testClass1);
- int main()
- {
- CPPUNIT_NS::TestResult controller;
- CPPUNIT_NS::TestResultCollector result;
- controller.addListener( &result );
- CPPUNIT_NS::TestRunner runner;
- runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
- runner.run( controller );
- CPPUNIT_NS::CompilerOutputter out( &result, std::cout );
- out.write();
- return 0;
- }
makefile文件如下:
EXE=test
SRC=test.cpp
INC_PATH=-I ../src -I (cppunit頭文件的目錄) -I(依賴的其他頭文件路徑)
LIB_PATH=-L (cppunit動(dòng)態(tài)庫所在的目錄) -L (依賴的其他庫所在目錄)
LIB=-lcppunit -ldl
all:
g++ $(SRC) $(LIB_PATH) $(LIB) $(INC_PATH) -o $(EXE)
再有新的需要測試類,增加相應(yīng)的測試類,稍微修改下test.cpp即可(增加一句#include,一句CPPUNIT_TEST_SUITE_REGISTRATION)。
保證開發(fā)結(jié)束后,解析類、算法類等不會(huì)有錯(cuò)誤。
(2)白盒測試階段
這個(gè)基本是功能邏輯性測試,檢測所有數(shù)據(jù)結(jié)構(gòu)按要求變化以及保證各線程之間變化的一致性。這是最基本也是最全面的一次測試,保證測試的功能覆蓋率100%。白盒測試期間可以在代碼里加一些宏編譯選項(xiàng)或者增加程序交互功能用于觀察所有數(shù)據(jù)結(jié)構(gòu)的變化。
保證測試完畢沒有功能性、邏輯性的錯(cuò)誤。
(3)內(nèi)存測試階段
使用valgrind檢測顯式內(nèi)存泄漏、內(nèi)存讀寫錯(cuò)誤。
從http://www.valgrind.org/下載最新版本,解壓,看安裝文檔,一般是./configure & make & make install。
檢測內(nèi)存一般使用命令valgrind --tool=memcheck -v --leak-check=full ./待測程序錯(cuò)誤的地方會(huì)用==×××==(×××表示數(shù)字)標(biāo)出。
使用一路模擬客戶端做陪測。保證測試完畢,單路客戶端陪測的情況下沒有任何的顯式內(nèi)存泄漏,沒有任何的內(nèi)存讀寫錯(cuò)誤。
(4)寫批量客戶端模擬程序
建議熟悉一門方便socket編程的腳本語言,推薦perl。腳本語言簡單,實(shí)現(xiàn)快速,特適合做陪測。
首先寫一個(gè)能讀取配置文件信息,按配置文件的要求向相應(yīng)的server,按配置文件的流程發(fā)送信令的perl程序。
下面是我rtsp相關(guān)的一個(gè)server陪測的配置文件:
ip=127.0.0.1
port=9115
url=rtsp://172.24.202.190:554/asset/service?USERID=320101312345670001&ChanelNo-PUID=0-320101000200000001&PlayMethod=0
其中ip是server IP,port是rtsp端口,url是發(fā)送信令帶的url。<>表示按順序發(fā)送的信令,這個(gè)配置文件表示先發(fā)送一個(gè)setup,然后sleep 2秒,再發(fā)送一個(gè)play,然后sleep 2秒,繼續(xù)......這個(gè)程序可作為(3)中的陪測程序。
在上面程序的基礎(chǔ)上修改,讀取配置文件后,死循環(huán)按順序發(fā)送信令,假設(shè)該程序稱做B。
寫一個(gè)新的perl文件,完成如下功能,起幾十路使用某配置文件的B程序,sleep幾秒后,再起幾十路使用其它配置文件的B程序.....,或者一起起也可以,自行設(shè)計(jì),最后killall所有,從頭循環(huán)運(yùn)行。
總之盡可能的模擬客戶端的所有行為,包括突然斷聯(lián)等,并且保證一定的壓力。
(5)壓力下測試內(nèi)存
繼續(xù)在valgrind下測試,使用(4)中的測試腳本做配測。
保證壓力下無異常狀態(tài)、無數(shù)據(jù)不一致狀態(tài)、無顯式內(nèi)存泄漏、無內(nèi)存讀寫異常。
(6)穩(wěn)定性以及內(nèi)存泄漏測試
陪測腳本起幾百路客戶端,保證主程序的cpu占用率在70%以上,持續(xù)運(yùn)行20多小時(shí)。
測試期間,關(guān)注進(jìn)程對內(nèi)存的占用率,是保持在恒定水平還是隨運(yùn)行時(shí)間的增長而增長。
測試完畢,保證主程序負(fù)荷運(yùn)行長時(shí)間而不宕機(jī)、沒有內(nèi)存泄漏發(fā)生。
(7)代碼覆蓋率測試。gcov
gcov是隨gcc安裝的,可以檢查陪測程序?qū)δ繕?biāo)程序的代碼覆蓋情況。
不斷修改測試腳本,保證測試盡量全面。代碼被執(zhí)行的次數(shù)也可以做為以后性能測試的一個(gè)參考。
(8)性能測試。gprof
同gcov一樣,gprof也是隨gcc安裝的,它可以檢測目標(biāo)程序中所有函數(shù)的調(diào)用時(shí)間,并根據(jù)消耗時(shí)間排序,方便找出性能瓶頸。
找出系統(tǒng)的主要性能瓶頸,經(jīng)過性能測試后,一般會(huì)發(fā)現(xiàn)影響系統(tǒng)的主要因素還是數(shù)據(jù)結(jié)構(gòu)和算法。
C++ Server測試期間,任何的coredump/任何的內(nèi)存讀寫異常,務(wù)必處理掉。墨菲法則說,一個(gè)事情如果有可能變糟,事實(shí)則是會(huì)變的更糟。任何一個(gè)微小的、出現(xiàn)幾率極小的bug,如果不在研發(fā)測試階段解決,都可能造成以后更大代價(jià)的返工,甚至給客戶的運(yùn)營帶來災(zāi)難。希望在每個(gè)人身上生效的都是馬太效應(yīng),而不是墨菲法則。
【編輯推薦】