最近几周一直在学习CI框架,网上(http:codeigniter.org.cn)有很多关于这个框架的文章和视频教程,利用CI框架可以方便快速地建议自己的网站。而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:\DinerSystem\Sinafood\tests>phpunit
PHPUnit 3.6.11 by Sebastian Bergmann.
Configuration read from D:\DinerSystem\Sinafood\tests\phpunit.xml
..................
Time: 1 second, Memory: 4.00Mb
[30;42m[2KOK (18 tests, 24 assertions)
[0m[2K
D:\DinerSystem\Sinafood\tests>
你运行结果中的tests和assertions个数可能和我的不一样,因为我现在的结果加了其他的测试用例,只要出来这个结果,说明测试可以进行了。
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测试用例结构
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));
}
}
B,Model测试用例结构:
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
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
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
菜品ID |
菜品名称 |
单价 |
餐馆 |
数量 |
=$rows->id?> |
=$rows->name?> |
=$rows->price?> |
=$rows->owner?> |
=$rows->count?> |
(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的测试:
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”);
}
//测试showmenu的index()
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>/isU",$out,$arr); //对返回的数据进行筛选
//print_r($arr);
$this->assertSame('15',$arr[1][7]);//判断筛选的结果
$this->assertSame('28',$arr[1][37]);
}
}
?>
B,对model进行测试
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:\DinerSystem\Sinafood\tests>phpunit
PHPUnit 3.6.11 by Sebastian Bergmann.
Configuration read from D:\DinerSystem\Sinafood\tests\phpunit.xml
..................
Time: 4 seconds, Memory: 4.00Mb
[30;42m[2KOK (18 tests, 24 assertions)
[0m[2K
D:\DinerSystem\Sinafood\tests>
(5)排查测试中存在的错误
测试用例在运行过程中会出现各种错误的情况,这个时候就需要你对其进行排查。我建议:(a)对要检测的结果进行输出,以方便知道哪儿发生了错误。(b)程序中使用CI框架标准的数据操作函数,否则也会出错。其他的情况也会非常多,就不一一列举了,具体问题具体分析吧!
推荐阅读
-
本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ...
[详细]
蜡笔小新 2023-12-14 00:31:35
-
本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ...
[详细]
蜡笔小新 2023-12-14 17:15:38
-
-
本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ...
[详细]
蜡笔小新 2023-12-14 16:00:02
-
使用Ubuntu中的Python获取浏览器历史记录原文: ...
[详细]
蜡笔小新 2023-12-14 08:57:59
-
本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ...
[详细]
蜡笔小新 2023-12-13 17:48:58
-
本文介绍了使用Oracle10g进行备份导入的方法及相关注意事项,同时还介绍了2019年独角兽企业重金招聘Python工程师的标准。内容包括导出exp命令、删用户、创建数据库、授权等操作,以及导入imp命令的使用。详细介绍了导入时的参数设置,如full、ignore、buffer、commit、feedback等。转载来源于https://my.oschina.net/u/1767754/blog/377593。 ...
[详细]
蜡笔小新 2023-12-13 09:26:23
-
本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ...
[详细]
蜡笔小新 2023-12-12 18:18:49
-
本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ...
[详细]
蜡笔小新 2023-12-14 17:24:50
-
本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ...
[详细]
蜡笔小新 2023-12-14 17:15:19
-
本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ...
[详细]
蜡笔小新 2023-12-14 14:29:36
-
在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ...
[详细]
蜡笔小新 2023-12-14 10:57:47
-
本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ...
[详细]
蜡笔小新 2023-12-14 10:11:46
-
本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ...
[详细]
蜡笔小新 2023-12-13 16:16:05
-
一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ...
[详细]
蜡笔小新 2023-12-13 13:52:40
-
本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ...
[详细]
蜡笔小新 2023-12-13 13:02:24
-
|