zoukankan      html  css  js  c++  java
  • CI 的 单 元 测 试

        最近几周一直在学习CI框架,网上(http://codeigniter.org.cn/)有很多关于这个框架的文章和视频教程,利用CI框架可以方便快速地建议自己的网站。而CI还有一个意思就是持续化集成,所以就要求测试也自动化。但是我搜了一下,这方面的文档不多,实在没有办法,就把CI与单元测试相关的源码给全看了一下,虽然不是太懂,但是已经可以自己写测试用例了,现在总结一下,希望对大家有所帮助。

    初步接触CI的单元测试

       CI是利用PHPUNIT进行测试的,而框架里面自带的也有写好的测试用例,大家可以拿来练一下手.

    1)安装PHPUNIT,具体安装方法,在不同的操作系统下也不相同,网上有很多方法,可以参照一下。安装完成后会显示下面的效果,说明安装成功:

    C:>phpunit --version

    PHPUnit 3.6.11 by Sebastian Bergmann.

      2)进入你放置CI代码下的tests文件夹下,运行phpunit命令。

    D:DinerSystemSinafood ests>phpunit

    PHPUnit 3.6.11 by Sebastian Bergmann.

    Configuration read from D:DinerSystemSinafood estsphpunit.xml

    ..................

    Time: 1 second, Memory: 4.00Mb

    [30;42m[2KOK (18 tests, 24 assertions)

    [0m[2K

    D:DinerSystemSinafood ests>

          你运行结果中的testsassertions个数可能和我的不一样,因为我现在的结果加了其他的测试用例,只要出来这个结果,说明测试可以进行了。

    CI单元测试结构介绍

    (1)测试文件结构

    在框架根目录下的tests文件夹中有以下几个文件夹,其作用如下:

    Controllers:存放对Application中的controller中的文件进行测试。

    Fixtures:存放测试数据文件yml及其他测试(暂时没有搞明白)。

    Helpers: 存放对Application中的helpers中的文件进行测试。

    Libs: 存放对Application中的libs中的文件进行测试。

    Models: 存放对Application中的models中的文件进行测试。

    System: 存放对Application中的system中的文件进行测试。

    该文件夹下还有如generate, generate.php, getops.php, holder phpunit.xml在写测试用例的时候我们不用修改,暂忽略之。

    application文件夹下还有一个third_party的文件夹,这个里面有CIUnit文件夹,里面存放着生成和回收测试数据的Fixture.php,还有其他进行测试相关驱动的文件,目前我没有研究它们的工作方法。

    (2)测试数据库

    如果你要测试的程序有数据操作的话,在测试之间要先往数据库中存放一些儿测试数据,测试完成之后要清除数据,不过这些儿工作CI框架已经帮你完成,你只要建测试数据库及对应的表就行了。测试数据库必须以“­_test”结尾,其连接配置在:application/config/testing/database.php中设置,方法和CI的正常配置一样。如果在文件中配置了$db['default']['dbprefix'] = 'ff_';项,则要注意:测试表必须以“ff_”开头。

    测试数据存放在tests/fixtures文件夹中,测试文件以原项目中的表名_fixt.yml”命名,否则程序无法读取其中的数据。Yml文件中的数据格式如下:

    现有测试数据表:

    ff_phone_carrier(

    name     varchar(255)

    txt_address    varchar(255)

       txt_message_length      int(11));

    很显然原工程中的表名为:phone_carrier, 现在测试数据文件中:phone_carrier_fixt.yml:

    1:                         //此为第一条记录

        name: 'Verizon'          //对应字段的值

        txt_address: '@vzpix.com'

        txt_message_length: 160

    2:

        name: 'AT&T'

        txt_address: '@mms.att.net'

        txt_message_length: 160

    (3)测试用例结构

    A,Controller测试用例结构

    <?php

     

    class SomeControllerTest extends CIUnit_TestCase

    {

      public function setUp()

      {

          // Set the tested controller

          $this->CI = set_controller('welcome');//设置要测试的controller,本例为welcome

      } 

      public function testWelcomeController()

      // 调用被测试的Controller中的方法 index()

          $this->CI->index();

          // 获得输出结果

          $out = output();       

          // 对结果进行检测

          $this->assertSame(0, preg_match('/(error|notice)/i', $out));

      }

    }

    BModel测试用例结构:

    <?php

     

    class PhoneCarrierModelTest extends CIUnit_TestCase

    {

      protected $tables = array(

          'ff_phone_carrier' => 'phone_carrier'  //设置数据表:测试用例表对=>正式表

      ); 

      private $_pcm; 

      public function __construct($name = NULL, array $data = array(), $dataName = '')

      {

          parent::__construct($name, $data, $dataName);

      } 

      public function setUp()

      { //测试开始执行的方法

          parent::setUp();       

               

          $this->CI->load->model('Phone_carrier_model');

          $this->_pcm = $this->CI->Phone_carrier_model;

      } 

      public function tearDown()

      { //测试结束执行的方法

          parent::tearDown();

      } 

      // ------------------------------------------------------------------------ 

     

      public function testGetCarriers(array $attributes, $expected)

       //具体的测试方法

          $actual = $this->_pcm->getCarriers($attributes);       

          $this->assertEquals($expected, count($actual));

      }

      public function GetCarriersProvider()

      { //提供检测数据的方法,也可以直接写数据

          return array(

              array(array('name'), 5)

          );

      

    }

     

    实战演习

    1,要测试的项目

    现有一小网页显示数据库foodfeed中的一个表单food中的数据,各个文件内容如下:

    (1) Controller : showmenu.php

    <?php

    class showmenu extends CI_Controller {

            public function __construct()

           {

                       parent::__construct();

                     $this->load->model(showmenu _m');

                

           //查询显示所有数据

           public function index()

            {

                  $data['query']=$this-> showmenu _m->getfoodlist();

                  $this->load->view(showmenuview,$data);

            }

    }

    ?>

    (2)model: showmenu _m.php

    <?php

    class showmenu _m extends CI_Model

     

        function __construct()

        {

           $this->load->database();

         }

        //获取food表中的所有记录

        function getfoodlist()

                  

            $this->db->select('*')->from('food');

             $query = $this->db->get();      

            return $query->result();

        }

    }

    ?>

    (3)view: showmenuview.php

    <html xmlns="http://www.w3.org/1999/xhtml">

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <title>推荐菜品展示</title>

    </head>

        <body>

    <div>

            <table border=1>

                <tr>

                    <td>菜品ID</td>

                    <td>菜品名称</td>

                     <td>单价</td>

                    <td>餐馆</td>

                    <td>数量</td>

                </tr>          

             <?php foreach ($query as $rows):?>

                <tr>                  

                    <td><?=$rows->id?></td>

                    <td><?=$rows->name?></td>

                    <td><?=$rows->price?></td>

                    <td><?=$rows->owner?></td>

                    <td><?=$rows->count?></td>               

                </tr>

               <?php endforeach;?>

            </table>

        </div>  

    </body>

    </html>

    (4)程序所用的数据表结构如下:

    Foodfeed.food(

    id        int(11),

    name  varchar(45),

    owner         varchar(45),

    price  int(11),

    count int(11) );

    2,测试战争

    1)建立测试数据库foodfeed_test,对应的表:ff_food,表结构同正式表,表中无任何数据。

    2)在tests/fixtures中建测试数据文件food_fixt.yml,内容如下:

    ## YAML Template.

    1:

      id: 1

      name: "鱼香肉丝"

      owner: "面香"

      price: 15

      count: 12

    2:

      id: 2

      name: "红烧带鱼"

      owner: "大食代"

      price: 28

      count: 1

     3)创建测试文件

       A,controller的测试:

     <?php

    class ShowMenuTest extends CIUnit_TestCase

         

           protected $tables = array(

                       'ff_food' => 'food'  //设置表对应关系

                  );         

             private $_pcm;        

             public function __construct($name = NULL, array $data = array(), $dataName = '')

             {

                       parent::__construct($name, $data, $dataName);

             }

        public function setUp()

              //装载测试数据

            parent::setUp();

            $this->CI->load->model(' showmenu_m');

                       $this->_pcm = $this->CI-> showmenu_m;

                       // Set the tested controller

                       $this->CI = set_controller(“showmenu”);

             }        

            //测试showmenuindex()

             public function testIndexController()

                    

                       // Call the controllers method

                       $this->CI->index();           

                       // Fetch the buffered output

                       $out = output();

            // Check if the content is OK

                 preg_match_all("/<td>(.*)</td>/isU",$out,$arr);  //对返回的数据进行筛选

            //print_r($arr);

            $this->assertSame('15',$arr[1][7]);//判断筛选的结果

            $this->assertSame('28',$arr[1][37]);            

                

                 

    }

    ?>

    B,model进行测试

    <?php

    class ShowMenuModelTest extends CIUnit_TestCase

    {

           protected $tables = array(

                  'ff_food' => 'food'

           );         

           private $_pcm;      

           public function __construct($name = NULL, array $data = array(), $dataName = '')

           {

                  parent::__construct($name, $data, $dataName);

           }      

           public function setUp()

           { //装载测试数据

                  parent::setUp();            

                  $this->CI->load->model('recommand_m');

                  $this->_pcm = $this->CI->recommand_m;

             

           public function tearDown()

           {

                  parent::tearDown();

                  

            //测试全部数据显示

            public function testmodelindex()

              

             $actual = $this->_pcm->getfoodlist( );        

                $this->assertEquals(15, $actual[0]->price);//检测返回的结果

             $this->assertEquals(28, $actual[6]->price);             

             

         }

    ?>

    (4)运行测试用例

    D:DinerSystemSinafood ests>phpunit

    PHPUnit 3.6.11 by Sebastian Bergmann.

    Configuration read from D:DinerSystemSinafood estsphpunit.xml

    ..................

    Time: 4 seconds, Memory: 4.00Mb

    [30;42m[2KOK (18 tests, 24 assertions)

    [0m[2K

    D:DinerSystemSinafood ests> 

    5)排查测试中存在的错误

        测试用例在运行过程中会出现各种错误的情况,这个时候就需要你对其进行排查。我建议:(a)对要检测的结果进行输出,以方便知道哪儿发生了错误。(b)程序中使用CI框架标准的数据操作函数,否则也会出错。其他的情况也会非常多,就不一一列举了,具体问题具体分析吧!

     

    ----夫英雄者,胸怀大志,腹有良谋,有包藏宇宙之机,吞吐天地之志者也。
  • 相关阅读:
    jfinal的configPlugin基本配置代码
    jfinal的maven配置
    access denied XXXXXXXXXXXX
    常见排序算法小结
    String、StringBuffer与StringBuilder之间区别
    进程间的通信方式
    从右上角到左下角沿反对角线打印方阵中的元素
    快乐数问题
    数组循环移位问题
    HTTP协议报文格式
  • 原文地址:https://www.cnblogs.com/eagleking0318/p/6521089.html
Copyright © 2011-2022 走看看