• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    PHP Unit自動(dòng)化單元測(cè)試技術(shù)研究

    2012-01-15 06:03:16王莉軍
    電子設(shè)計(jì)工程 2012年23期
    關(guān)鍵詞:單元測(cè)試測(cè)試函數(shù)文件夾

    王莉軍

    (渤海大學(xué) 大學(xué)計(jì)算機(jī)教研部,遼寧 錦州 121013)

    一個(gè)函數(shù)、一個(gè)類編寫完成,到底能不能正確工作?怎么測(cè)試它?PHP單元測(cè)試是個(gè)好辦法,它提供了自動(dòng)化測(cè)試的方法,使敏捷開發(fā)的自動(dòng)化測(cè)試成為可能。

    1 單元測(cè)試的前提條件(單元測(cè)試的基礎(chǔ))

    1)代碼具備基本可測(cè)試性。及要求被測(cè)試函數(shù)具備輸入輸出。(本測(cè)試方案未考慮無輸入輸出函數(shù)的測(cè)試)

    2)被測(cè)函數(shù)盡可能分情況說明輸入輸出。及期望輸入及輸出和非期望輸入對(duì)應(yīng)輸出。

    3)被測(cè)還是應(yīng)該有基本的函數(shù)說明,表明函數(shù)的功能[1]。

    2 單元測(cè)試管理

    1)對(duì)于某個(gè)系統(tǒng),不同層的代碼放置于不同文件夾下。以talk為例,其有dataaccess層和logic層,那么其dataaccess層代碼放置于文件夾dataaccess之下。而單元測(cè)試文件的布局則和系統(tǒng)代碼布局一一對(duì)應(yīng)。對(duì)于某個(gè)文件a.php,其對(duì)應(yīng)的測(cè)試文件命名則為aTest.php。而對(duì)于a.php中某個(gè)函數(shù)method來說,其對(duì)應(yīng)的測(cè)試函數(shù)命名應(yīng)該為testMethod[2]。

    2)每個(gè)測(cè)試函數(shù)應(yīng)該包括一定的注釋。不依賴于dataprovider的情況。

    /**

    *@author****

    *@note****

    *@expect input**

    *@expect output**

    *@unexpect input**

    *@unexpect output**

    */

    依賴于dataprovider的情況:

    /**

    *@author**** /**

    *@note**** *@expect 1,2,3

    *@dataprovider** *@unexpect 4,5,6

    */ */

    1)在測(cè)試根目錄下應(yīng)該包含有各文件夾下文件測(cè)試覆蓋率統(tǒng)計(jì)文件夾。

    2)單元測(cè)試代碼應(yīng)該避免過多的依賴關(guān)系。盡量減少對(duì)外部環(huán)境依賴,減少對(duì)外部代碼具體實(shí)現(xiàn)依賴,減少對(duì)測(cè)試內(nèi)部函數(shù)之間的依賴[3]。

    3 單元測(cè)試編碼(通過場(chǎng)景展示)

    場(chǎng)景一:一般簡(jiǎn)單情況的函數(shù)測(cè)試

    1)被測(cè)試class如下:

    Class MyMathClass

    {

    /*

    **add two given values,and return the sun

    */

    Public function add($a,$b)

    {

    Return$a+$b;

    }

    }

    ?>

    2)測(cè)試 class如下:

    Require_once ‘PHPUnit/Framework.php’;

    Require_once ‘MyMathClass.php’;

    /**

    *Test class for MyMathClass.

    *Generated by PHPUnit on 2011-03-31 at 13:11:05

    */

    Class MyMathClassTest extends PHPUnit_Framework_Testcase

    {

    /**

    *@var MyMathClass

    *@access protected

    */

    Protected$object;

    /**

    * Setsup the fixture,forexample,opens a network connection.

    *This method is called before a test is executed.

    *

    *@access protected

    */

    Protected function setup()

    {

    $this->object–new MyMathClass;

    }

    /**

    * Tears down the fixture,for example,closes a network connection.

    *this method is called after a test is executed.

    *

    *@access protected

    */

    Protected function tearDown()

    { }

    /**

    *@todo ImpLement testAdd().

    */

    Public function testAdd(){

    //Remove the following lines when you implement this test.

    $this->assertEquales(3,$this->object->add(1,2));

    }

    }

    ?>

    簡(jiǎn)單單元測(cè)試class里僅僅包含一個(gè)被測(cè)試的method的,而在生成的測(cè)試class里邊包含了除對(duì)應(yīng)add函數(shù)的測(cè)試函數(shù)testAdd以外,還包含setUp和tearDown函數(shù)。其中setUp是在每個(gè)測(cè)試函數(shù)執(zhí)行之前都會(huì)自動(dòng)執(zhí)行一遍,用來自動(dòng)建立每個(gè)method的獨(dú)立測(cè)試上下文環(huán)境,通用tearDown在每個(gè)測(cè)試函數(shù)執(zhí)行之后執(zhí)行一遍,用來清除此method執(zhí)行之中設(shè)定的上下文[4]。而testAdd則用來對(duì)add函數(shù)進(jìn)行測(cè)試。testAdd函數(shù)中只包含一條語句,這條語句即假定通過調(diào)用add函數(shù)執(zhí)行1加2,我們期望其返回的結(jié)果與3相等。如果相等,執(zhí)行結(jié)果則通過,如果不相等則測(cè)試失敗,說明代碼并沒有完成我們想要的功能,如圖1所示。

    圖1 測(cè)試結(jié)果Fig.1 Test execution results

    場(chǎng)景二:針對(duì)數(shù)據(jù)庫增刪查改函數(shù)的測(cè)試

    1)被測(cè)試函數(shù)如下:

    /**

    *Message的數(shù)據(jù)訪問

    */

    Class DMessage extends Dataaccess{

    /**

    *單條消息(通過緩存)

    */

    Public static function get($message_id) {

    $message=self==getCache($message_id);

    If(!$message){

    $message=self==getByDb($message_id);

    If(self==isTure($message)) {

    self==setCache($message);

    }else{

    Return$message;

    }

    }

    Return$message;

    }

    2)測(cè)試函數(shù)如下:

    Class DMessageTest extends CDbTestCase

    {

    Public$fixture=array(

    ‘message’=>’:tb_message’,

    );

    /**

    *Implement testGet() {

    *

    */

    Public function testGet() {

    $message=$this->message[‘sample1’]

    DMessage==deleteCache($message[‘id’]);

    $ret=DMessage==get($message[‘id’]);

    $this->assertEquals($message[‘id’], $ret[‘id’]);

    }

    3)datafixture

    Return array(

    ‘sample1’=>array(

    ‘id’=>1,

    ‘user_id’=>1,

    ‘content’=>’unit test’,

    ‘source’=>’unit test’,

    ‘lat’=>1,

    ‘lon’=>1,

    Location’=>1,

    ‘forword_count’=>0,

    ‘reply_count’=>0,

    ‘pic_id’=>0,

    ‘pic_filename’=>’’,

    ‘pic_id_water’=>0,

    ‘pic_filename_water’=>’’,

    ‘created_time’=>’2011-03-21 11:21:59’,

    ‘last_forward’=>0

    ‘is_deleted’=>0,

    ‘fid’=>0,

    ‘is_safe’=>0’

    ‘media_json’=>’’

    ‘message_json’=>’’,

    上面的DMessage class下的get函數(shù)是去獲取一條關(guān)于message的記錄。忽略此函數(shù)間的依賴性來說,如果在測(cè)試的時(shí)候,cache中不存在關(guān)于此message的記錄,則需要往數(shù)據(jù)庫中去取此條記錄,而在測(cè)試此函數(shù)的時(shí)刻,數(shù)據(jù)庫中是否存在需要查找的message記錄是無法確定的,所以會(huì)導(dǎo)致函數(shù)的上下文環(huán)境不確定,進(jìn)而導(dǎo)致測(cè)試無法進(jìn)行?;蛘咴诿看螠y(cè)試之前手動(dòng)地去刪除或者添加記錄,在測(cè)試過程中還要防止其他人刪除此記錄[5]。在測(cè)試函數(shù)中出現(xiàn)了fixtrue變量,這個(gè)變量的作用就是在每個(gè)測(cè)試method執(zhí)行之前清空數(shù)據(jù)庫中某張或者多張表里的數(shù)據(jù),然后插入給定的數(shù)據(jù),給定數(shù)據(jù)通過在fixture文件中設(shè)置,而fixture中文件命名規(guī)則為表名字.php。(例如數(shù)據(jù)中有一張表名字為tb_message,則fixture里有一個(gè)文件名字為tb_message.php,文件內(nèi)容對(duì)應(yīng)為一個(gè)數(shù)組,數(shù)組每個(gè)變量對(duì)應(yīng)數(shù)據(jù)庫表中一條記錄)。通過使用fixture,能夠使單元測(cè)試在一個(gè)給定的上下文環(huán)境中進(jìn)行[6]。

    場(chǎng)景三:被測(cè)試的函數(shù)存在對(duì)其他函數(shù)調(diào)用

    解決方案:1)使用phpunit自帶的mock或者stub方法2)使用 runkit中的 method_redifine 方法()。

    1)被測(cè)試class

    Class LContactNsg

    {

    /**

    *@param$userId

    *@param$sendUserId

    *@return unknown_type

    */

    Public static function agree($userId,$sendUserId)

    {

    If(DContactMsg==check($userId,$sendUserId))

    {

    DContactMsg==delete(array($userId,$sendUserId));

    DContactMsg==delete(array($sendUserId, $userId));

    If (false!==DContacts==insert(array($userId,$sendUserId)))

    return true;

    Else

    return false;

    }

    return true;

    }

    }

    2)測(cè)試 class

    require_once’/home/work/htdocs/php/development/liuxiang/talk/dataaccess/DContactMsg.php’;

    require_once’CsvFileIterator.php;

    /**

    *Test class for LContactMsg.

    *Generated by PHPUnit on 2011-05-06 at 16:20:13.

    */

    Class LContactMsgTest extend CTestCase

    {

    /**

    *Implement testAgree().

    *@dataaprovider agreeProvider

    */

    Public function testAgree ($userId,$sendUserId,$expect,$re1,$re2,$re3){

    runkit_method_redefine (‘DContactMsg’,’check’,’’,

    “$re1,

    RUNKIT_ACC_PUBLIC);

    runkit_method_redefine(‘DContactMsg’,’delete’,’’,

    “$re2,

    RUNKIT_ACC_PUBLIC);

    runkit_method_redefine(‘DContactMsg’,’insert’,’’,

    “$re3,

    RUNKIT_ACC_PUBLIC);

    $result=LContactMsg==agree ($userId, $sendUserId,$expect,$re1,$re2,$re3);

    $this->assertEquals($result,$expect);

    }

    Public function agreeProvider(0

    { return array(

    array (1,8,true,’return true;’,’ return true;’’return true;’)

    );

    }

    }

    ?>

    由于單元測(cè)試關(guān)注點(diǎn)為當(dāng)前測(cè)試函數(shù)是否能夠能正確地完成相應(yīng)的任務(wù),而不關(guān)注被此函數(shù)調(diào)用函數(shù)能否正確完成任務(wù)。而如果不對(duì)調(diào)用函數(shù)進(jìn)行mock,當(dāng)此函數(shù)測(cè)試失敗時(shí),我們便無法立刻區(qū)分是當(dāng)前被測(cè)試函數(shù)出現(xiàn)bug還是被被測(cè)函數(shù)調(diào)用函數(shù)出現(xiàn)bug。因此我們可以mock被被測(cè)函數(shù)調(diào)用的函數(shù),讓其返回我們所期望的值,這樣就可以方便快捷地測(cè)試被測(cè)函數(shù)是否滿足要求[7]。此測(cè)試class中使用的是runkit函數(shù)庫中的runkit_method_redifine方法。而phpunit中也有相應(yīng)的處理方法,及mock和stub。但是phpunit中的方法不能處理static方法調(diào)用,而runkit無此限制[8]。

    4 結(jié) 論

    自動(dòng)化測(cè)試的目的是減少代碼的bug,一旦你開始習(xí)慣使用自動(dòng)化測(cè)試,你將發(fā)現(xiàn)你的代碼的bug在減少,你的代碼的可信性在增加,有了可信的保證,你可以對(duì)你的代碼進(jìn)行大膽的重構(gòu),取得事倍功半的效果[9]。

    [1]吳高峽,王芙蓉.單元測(cè)試的自動(dòng)化實(shí)踐[J].計(jì)算機(jī)與數(shù)字工程,2007(1):15-17.WU Gao-xia,WANG Fu-rong.Unit test automation practices[J].Computer and Digital engineering,2007(1):15-17.

    [2]陳靜.單元測(cè)試在軟件開發(fā)過程中的作用[J].艦船電子對(duì)抗,2006(3):25-28.CHEN Jing.Role of unit testing in software development[J].Warship EW.,2006(3):25-28.

    [3]陳站華.軟件單元測(cè)試[J].無線電通信技術(shù),2003(5):124-126.CHEN Zhan-hua.Software unit test[J].Radio Communications Technologies,2003(5):124-126.

    [4]侯鯤,林和平,楊威.設(shè)計(jì)模式在自動(dòng)單元測(cè)試框架中的應(yīng)用[J].計(jì)算機(jī)工程與應(yīng)用,2004(31):256-259.HOU Kun,LIN He-ping,YANG Wei.Application of design pattern in automated unit testing frameworks[J].Computer Engineering and Applications,2004(31):256-259.

    [5]林海,歐鋼,向?yàn)?軟件測(cè)試策略綜述[J].軟件導(dǎo)刊,2008(10):165-168.LIN Hai,OU Gang,XIANG Wei.Overview of software testing strategies[J].Software DVD Guide,2008(10):165-168.

    [6]張巍,尹海波,孫立財(cái).軟件的單元測(cè)試方法[J].光電技術(shù)應(yīng)用,2006(2):58-61.ZHANG Wei,YIN Hai-bo,SUN Li-cai.Software unit test method[J].Application of Opto-electronic Technology,2006(2):58-61.

    [7]王麗達(dá).論軟件系統(tǒng)的測(cè)試[J].經(jīng)濟(jì)研究導(dǎo)刊,2011(14):82-85.WANG Li-da.On testing of software systems[J].Economic Research Guide Magazine,2011(14):82-85.

    [8]許學(xué)軍.軟件測(cè)試軟環(huán)境的構(gòu)建與優(yōu)化[J].中國民航飛行學(xué)院學(xué)報(bào),2006(4):36-38.XU Xue-jun.Soft environment construction and optimization of software testing[J].Journal of China Civil Aviation Flying College,2006(4):36-38.

    [9]王鵬,習(xí)媛媛,馬麗.單元測(cè)試在軟件質(zhì)量保證中的應(yīng)用研究[J].山西財(cái)經(jīng)大學(xué)學(xué)報(bào),2009(S2):52-54.WANG Peng,XI Yuan-yuan,Ma Li.Study on the application of unit testing in software quality assurance[J].Journal of Shanxi University of Finance and Economics,2009(S2):52-54.

    猜你喜歡
    單元測(cè)試測(cè)試函數(shù)文件夾
    磁力文件夾
    調(diào)動(dòng)右鍵 解決文件夾管理三大難題
    具有收縮因子的自適應(yīng)鴿群算法用于函數(shù)優(yōu)化問題
    帶勢(shì)函數(shù)的雙調(diào)和不等式組的整體解的不存在性
    約束二進(jìn)制二次規(guī)劃測(cè)試函數(shù)的一個(gè)構(gòu)造方法
    TC一鍵直達(dá)常用文件夾
    電腦迷(2015年1期)2015-04-29 21:24:13
    一年級(jí)上冊(cè)第五單元測(cè)試
    一年級(jí)上冊(cè)一、二單元測(cè)試
    面向真實(shí)世界的測(cè)試函數(shù)Ⅱ
    第五單元測(cè)試卷
    怀远县| 鲁山县| 碌曲县| 平顺县| 东辽县| 平顶山市| 普宁市| 太谷县| 浮梁县| 晴隆县| 海门市| 焦作市| 临高县| 札达县| 咸阳市| 英吉沙县| 河西区| 泗阳县| 射洪县| 田林县| 始兴县| 蕉岭县| 义马市| 宜阳县| 永安市| 白山市| 平安县| 庄浪县| 凤山县| 诸城市| 和林格尔县| 铁力市| 武强县| 新源县| 乐业县| 山丹县| 郯城县| 左贡县| 锦州市| 临沧市| 公主岭市|