php单元测试视频,Php单元测试工具simpletest

一、分组测试

分组测试

运行测试用例作为分组的一部分,测试用例应该被放在没有运行码的文件中:

class FileTester extends UnitTestCase { ...

} class SocketTester extends UnitTestCase {

...

} ?>

尽可能多的用例出现在同一个文件中。他们将包含任何他们需要的代码,包括需要测试的库,但是不包括simpletest库。

如果你已经继承任何测试用例,在php 4中,你能这么使用:

class MyFileTestCase extends UnitTestCase { ...

} SimpleTest::ignore('MyFileTestCase');

class FileTester extends MyFileTestCase { ... } class SocketTester extends UnitTestCase { ... }

?>

Ignore告诉测试系统,忽略他的执行。

在php 5中,可以用abstract关键字:

abstract class MyFileTestCase extends UnitTestCase { ...

} class FileTester extends MyFileTestCase { ... }

class SocketTester extends UnitTestCase { ... }

下一步,我们创建组测试文件,叫做my_group_test.php。

我们用安全方法添加测试文件:

require_once('simpletest/reporter.php'); require_once('file_test.php');

$test = &new GroupTest('All file tests'); $test->addTestCase(new MyFileTestCase());

$test->run(new HtmlReporter()); ?>

这将在套餐运行之前,实例化测试用例,可以不用逐个去实例化测试用例。

也能按照下面的方法来做:

require_once('simpletest/reporter.php'); $test = &new GroupTest('All file tests');

$test->addTestFile('file_test.php'); $test->run(new HtmlReporter());

?>

这儿有2件事情容易产生错误,需要注意:

1. 这个测试文件可能已经被php解析,因此新类将不能被增加。你应该确认测试用例只包含在这个文件中,不在其他文件中。

2.要注意ignore的使用,并且自己派生的测试用例类必须是抽象类,而且必须在GroupTest::addTestFile之前调用ignore。

高级分组

上面的方法是放所有测试用例进一个大的文件。对于大型项目来讲,这有点不够灵活,你可能需要按照某种排序方式分组。

为了获得更大的灵活性,你可以子类化GroupTest,然后按照需要实例化:

require_once('simpletest/reporter.php'); class FileGroupTest extends GroupTest {

function FileGroupTest() {

$this->GroupTest('All file tests');

$this->addTestFile('file_test.php');

}

} ?>

现在我们能从分离的运行文件中调用测试:

$test = &new FileGroupTest();

$test->run(new HtmlReporter()); ?>

或者我们可以对用例进行分组后,进入一个大的分组。我们能自由的混合分组或单个单元测试,只要我们注意双重包含的问题。

$test->addTestFile('file_group_test.php'); $test->addTestFile('some_test_case.php');

$test->run(new HtmlReporter()); ?>

二、Mock对象

什么是mock对象?

单独测试一个类或方法里的代码,而不测试里面调用的其他类或方法的代码。即假定调用的其他类或方法都正常执行。

使用Mock Object的场合

实际对象的行为还不确定。

实际的对象创建和初始化非常复杂。

实际对象中存在很难执行到的行为(如网络异常等)。

实际的对象运行起来非常的慢。

实际对象是用户界面程序。

实际对象还没有编写,只有接口等。

创建mock对象

方法与创建服务器存根相同,我们需要的所有事情就是一个已经存在的类。假如说有下面这个数据库类:

class DatabaseConnection { function DatabaseConnection() {

} function query() {

} function selectQuery() {

} }

这个类没有实际实现代码。为了创建这个类的mock版本,我们需要包含mock类库,然后运行生成器:

require_once('simpletest/unit_tester.php'); require_once('simpletest/mock_objects.php');

require_once('database_connection.php'); Mock::generate('DatabaseConnection');

这生成了一个名为MockDatabaseConnection的克隆类。我们现在能在我们的测试用例中,实例化这个新类。

require_once('simpletest/unit_tester.php'); require_once('simpletest/mock_objects.php');

require_once('database_connection.php'); Mock::generate('DatabaseConnection');

class MyTestCase extends UnitTestCase { function testSomething() {

$connection = &new MockDatabaseConnection();

} }

作为操作者的mock

一个类的mock版本拥有所有方法,因此像$connection->query()这样的调用仍然是合法的。返回值是null,但是我们需要改变他:

$connection->setReturnValue(‘query’, 37)

现在任何时候我们调用$connection->query(),他的返回值都是37。我们能设置任何东西的返回值,一个数据库的hash或者一个持久化对象,都可以。参数在这儿是不相关的,我们总是能得到同样的返回值。

我们也能添加附加的方法到mock对象,也可以选择我们自定义的类名作为mock对象的类名。

Mock::generate('DatabaseConnection', 'MyMockDatabaseConnection', array('setOptions'));

这儿setOptions()方法被增加。

事情不总是那么简单。迭代就是一个通常的问题,如果在测试时总是返回同一个值,会引起死循环。因此我们需要建立一些值的序列。我们来看看下面的简单的迭代的例子:

class Iterator { function Iterator() {

} function next() {

} }

这是我们能设想的最简单的迭代。假设迭代总是返回字符串直到到达尾部(当他返回false时),我们能用下面的方法仿真:

Mock::generate('Iterator'); class IteratorTest extends UnitTestCase() {

function testASequence() { $iterator = &new MockIterator();

$iterator->setReturnValue('next', false);

$iterator->setReturnValueAt(0, 'next', 'First string');

$iterator->setReturnValueAt(1, 'next', 'Second string');

...

} }

另外一个需要小技巧的情况是重载get()方法。下面是一个保存名-值对的例子:

class Configuration { function Configuration() {

} function getValue($key) {

} }

这种基本配置往往随着机器的变化而变化,我们可以手工直接配置。虽然所有的数据都来自getValue方法,但是我们需要根据键返回不同的值。很幸运,mock提供这样的过滤系统:

$config = &new MockConfiguration(); $config->setReturnValue('getValue', 'primary', array('db_host'));

$config->setReturnValue('getValue', 'admin', array('db_user')); $config->setReturnValue('getValue', 'secret', array('db_password'));

然后我们可以这样调用:

$config->getValue('db_user')

他将返回“admin”。附加的参数,将尝试和前面的参数进行匹配。

$config->setReturnValue('getValue', false, array('*'));

$config->setReturnValue('getValue', false);

是不一样的。第一种情况接受任何单个的参数,第二种情况接受任何数量的参数。

有三种因素可以被同时使用,时间、参数、是否copy:

$complex = &new MockComplexThing(); $stuff = &new Stuff();

$complex->setReturnReferenceAt(3, 'get', $stuff, array('*', 1));

它将返回$stuff,只有在第三次调用,并且只有在第二个参数设置为1的时候。

最后一个技巧是,一个对象创建另外一个对象,也就是通常说的工厂模式。假设成功调用query后,返回一个记录集,可以通过next不断迭代获取值,直到返回false为止。这听起来有点像恶梦,实际上mock能做这样的事情。

看下面:

Mock::generate('DatabaseConnection'); Mock::generate('ResultIterator');

class DatabaseTest extends UnitTestCase { function testUserFinder() {

$result = &new MockResultIterator();

$result->setReturnValue('next', false);

$result->setReturnValueAt(0, 'next', array(1, 'tom'));

$result->setReturnValueAt(1, 'next', array(3, 'dick'));

$result->setReturnValueAt(2, 'next', array(6, 'harry'));

$connection = &new MockDatabaseConnection();

$connection->setReturnValue('query', false);

$connection->setReturnReference(

'query',

$result,

array('select id, name from users'));

$finder = &new UserFinder($connection);

$this->assertIdentical(

$finder->findNames(),

array('tom', 'dick', 'harry'));

} }

三、部分mock

四、输出报告

Simpletest非常好的遵循mvc模式。报告类是显示层。

在html中输出结果

详查HtmlReporter类的使用。

命令行输出结果

详查TextReporter类

require_once('simpletest/reporter.php'); $test = &new GroupTest('File test');

$test->addTestFile('tests/file_test.php'); $test->run(new TextReporter());

?>

远程测试

SimpleTestXmlParser

... $parser = &new SimpleTestXmlParser(new HtmlReporter());

$parser->parse($test_output); ?>

五、期望

六、Web测试器

七、测试表单

八、验证

九、可执行脚本的浏览器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值