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框架标准的数据操作函数,否则也会出错。其他的情况也会非常多,就不一一列举了,具体问题具体分析吧!

 

----夫英雄者,胸怀大志,腹有良谋,有包藏宇宙之机,吞吐天地之志者也。
原文地址:https://www.cnblogs.com/eagleking0318/p/6521089.html