测试的运行流程

最后更新于:2022-04-02 00:33:47

# 流程 1. 使用visit或者是submitForm发起请求 2. request::create构建请求 3. 使用App::run执行请求指定的操作 4. 操作执行完毕回显结果 5. App::run返回response 6. 使用see等等对执行结果进行断言 # 从App类讲起 项目的入口文件是index.php,该文件会调用thinkphp目录下的start.php。而start.php主要的两个作用就是导入base.php文件和运行app。 `App::run()->send();` App是thinkPHP/library/think目录下的一个类。从该文件中我们可以知道,run会接受一个参数(request)。当这个参数为空的时候TP就会解析实际上的请求,当这个参数不为空的时候,TP实际上解析的便是这个参数。 # request支持构建请求 在request中有一个方法create,这个方法传入相关的参数便可以构建一个请求。其返回值便是一个request,我们再将这个request传递给App运行即可。 `$response = App::run($request);` 这个response便是处理的结果,这个结果将会跟网页显示的内容的一模一样的,因此我们对这个结果进行断言,便可以完成对整个单元测试流程了。
';

原理

最后更新于:2022-04-02 00:33:45

[测试的运行流程](3.%E5%8E%9F%E7%90%86%E8%A7%A3%E6%9E%90/1.%E6%B5%8B%E8%AF%95%E7%9A%84%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B.md)
';

使用PHPUNIT断言

最后更新于:2022-04-02 00:33:43

';

使用测试套件

最后更新于:2022-04-02 00:33:40

# 使用测试套件 ## 功能测试 由于thinkphp的测试扩展是基于phpunit的,因此phpunit的所有功能,在thinkphp的测试扩展中也能够使用。 当项目开始变得复杂,有多个模块的时候,我们在开发某个功能的时候,通常希望只测试某个功能。 这个时候,我们就能够使用phpunit的命令选项:--filter了。 一些常见的过滤例子为: ``` --filter 'TestNamespace\\TestCaseClass::testMethod' --filter 'TestNamespace\\TestCaseClass' --filter TestNamespace --filter TestCaseClass --filter testMethod --filter '/::testMethod .*"my named data"/' --filter '/::testMethod .*#5$/' --filter '/::testMethod .*#(5|6|7)$/' ``` 更多内容请参考[phpunit](http://www.phpunit.cn/manual/current/zh_cn/textui.html#textui.clioptions) ## 套件测试 当项目有多个模块组成的时候,我们通常希望测试速度够快,又不用测试整个项目。这个时候,我们就可以使用phpunit的套件功能了。 测试套件有两种方式组织,分别为通过目录和通过xml组织,在这里推荐使用第一种。 有多少个功能模块的时候,就在tests目录下新建多少个目录,然后在测试的时候,使用以下命令: `php think unit tests/xxx` 通过这种方式,我们就能单独测试某个子目录下的测试了,这种也称之为测试套件。
';

对数据库进行断言

最后更新于:2022-04-02 00:33:38

由于TP测试框架更偏向于黑盒测试(实际上我们使用的是灰盒测试),因此在对数据库进行测试的时候,我们没有办法(或者是不方便)使用mock。所以我们使用TP测试框架的时候对数据操作进行测试的时候,我们需要为数据库的基境进行搭建。 > 1. 黑盒测试:测试人员不需要了解代码如何工作,只需要根据指定输入,断言输出。 > 2. 白盒测试:测试人员需要了解代码,用来帮助测试的进行。 > 3. 灰盒测试:黑盒和白盒的中间,使用黑盒方法的同时使用白盒测试。 TP的官方测试框架主要使用灰盒的测试方法,如果需要使用mock的话,可以使用快速入门中提到的测试库。 ## 安装DBUnit。 使用thinkUnit的时候安装的PHPUNIT依赖中是没有DBUNIT的。因此如果我们要对数据库进行测试的话,那么就需要安装DBUnit了。 可以在composer中的require-dev中添加以下的依赖: `"phpunit/dbunit": ">=1.2"` 然后更新composer即可。 `composer update` ## 编写测试用例 安装完DBUnit之后,我们就需要重新编写测试用例了。不过,TP本身的测试库并没有提供数据库测试的测试用例基类,因此需要我们自己编写。 ``` ......其他配置 ...... ``` 而后在getConnection方法为: ``` if ($this->conn === null) { if (self::$pdo == null) { self::$pdo = new \PDO( $GLOBALS['DB_DSN'], $GLOBALS['DB_USER'], $GLOBALS['DB_PASSWD'] ); } $this->conn = $this->createDefaultDBConnection(self::$pdo, $GLOBALS['DB_DBNAME']); } return $this->conn; ``` > 再走一步:但是这样的话,我们每个方法也需要写这样重复的内容。因此,我们还可以将其抽象为父类,然后再需要使用数据库的测试类中继承该类。
';

对网页进行断言

最后更新于:2022-04-02 00:33:36

TP单元测试扩展中对网页元素的断言是基于symfony部分组件的,因此在使用对网页断言的时候还需要安装一个CssSelector的symfony组件。打开命令行,切换到TP的根目录下,运行下列的命令: `composer require symfony/css-selector:2.8` 等待其安装后便可以了。下面我们使用几个例子来说明一下如何使用网页元素断言。 # seeInElement 断言某个元素内是否存在某个元素。 @param $element 指定的元素,如body @param $text 要断言的文本 @param $negate 是否断言不存在,默认为false 假设有如下的网页: ~~~ Hello ! ~~~ 如果要断言字符串hello存在于body元素内,而字符串test不存在body里面,我们可以这么写: ~~~ visit('/index/index/index')->seeInElement('body','hello'); $this->visit('/index/index/index')->seeInElement('body','test',TRUE); } } ~~~ # notSeeInElement 效果如同seeInElement中将第三个参数设置为true @param $element 指定的元素,如bod @param $text 要断言的文本 例子如上。 # seeLink 断言某个链接是否存在,当第二个参数被设置时,同时断言其链接。 @param $text 某个a元素的文本,比如`test`,那么这里应该是test @param $url 默认为null,即断言找到的链接其地址是否为该url 假设有如下的网页: ~~~ 百度一下你就知道 ~~~ 如果要断言链接百度一下你就知道的a标签的地址,可以如下: ~~~ visit('/index/index/index')->seeLink('百度一下你就知道','http://www.baidu.com'); } } ~~~ # notSeeLink 断言不存在某个链接。 @param $text 某个a元素的文本,比如`test`,那么这里应该是test @param $url 默认为null,即断言找到的链接其地址是否为该url 例子如上。 # SeeInField 对input或者是textArea的value进行断言。 @param $selector name的值或者是id值 @param $expected 期望valued的值 如下网页: ~~~
~~~ 我们即可以对name=test的input,也可以对id=myInput的input的value进行断言: ~~~ visit('/index/index/index')->seeInField('test','hello');//通过name定位元素 $this->visit('/index/index/index')->seeInField('myInput','hello');//通过id定位元素 } } ~~~ # notSeeInField 对input或者是textArea的value进行断言。 @param $selector name的值或者是id值 @param $expected 期望valued的值 例子如上。 # seeIsChecked 对某个input选中进行断言。 # notSeeIsChecked 对某个input不是选中进行断言。 # seeIsSelected 对某个inpust选择进行断言。 # notSeeIsSelected 对某个input不选择进行断言。 # seePageIs 对某个页面的uri进行断言。
';

seeXX断言系列

最后更新于:2022-04-02 00:33:34

在TP单元测试扩展中,增加的断言最多便是seeXX断言系列。在快速入门的例子中,我们就使用了see断言函数。在扩展中,还有其他的see函数,他的名字通常是seeXX,比如seeJson。 # see 接收两个参数,用于断言一个正则是否在结果中可以匹配。第二个参数是布尔值,当为假的时候断言第一个参数在结果中匹配。当为真的时候断言第一个参数不在结果中匹配。 @param string $text 欲查找的文本 @param boolean $negate 非操作 # notSee 本方法使用了see,并且设置see的第二个参数为真。 @param string $text 欲查找的文本 # seeJson 内部使用seeJsonContains,用于断言某个json是否在结果中 @param array $data 期望的json @param boolean $negate 非操作,为真时是期望$data不在结果中 # seeJsonEquals 断言json是否跟结果相等。 @param array $data 传入一个数组,排序再转换成json 其内部会将实际值转回成数组进行排序后再跟$data排序后转换成的json进行断言。 # seeJsonContains 断言某个json是否在结果中。 @param array $data 期望的与断言的json数据 @param boolean $negate 非操作 # seeModule 用于断言请求中的模块。 @param string @module 欲断言的模块名字 `$this->visit('/index/index/index')->seeModule('index');` # seeController 用于断言请求中的控制器。 @param string @controller 欲断言的控制器名字 `$this->visit('/index/index/index')->seeController('Index');` >注意,控制器首字母是需要大写的。 # seeAction 用于断言请求中的操作。 @param string @action 欲断言的操作名字 `$this->visit('/index/index/index')->seeAction('index');` # seeStatusCode 用于断言response的状态码。 @param int $status 状态码 # seeHeader 用于断言response的head部。 @param string $headerName 头部的某个项 @param string $value 项值 # seeCookie 用于断言Cookie中是否存在某个值。 @param string $cookieName cookie的某个项名 @param string $value 项值
';

对模板变量进行断言

最后更新于:2022-04-02 00:33:31

在TP3.X中,我们通常使用$this->display()将一个模板渲染到网页上面去。比如在Index模块下面,我们新建一个view目录,然后再创建一个index目录,在其中创建一个html文件为index.html。如果要将这个html文件渲染到网页上面去的话,在TP5.X中,我们可以使用下面的语句: `return view('index');` 如果我们要在一个网页中输出变量的话,我们可以在view助手函数的第二个参数中将值传入进去。 HTML网页: ~~~ Hello {$name}! ~~~ 其对应的PHP代码: ~~~ 'c7']); } } ~~~ 那么如果我们要对上面的模板变量进行测试的话,我们可以使用下面三种方法: 1. assertViewHas 2. assertViewHasAll 3. assertViewMissing 第一个函数接受一个key值和一个value。 第二个函数则接受一个由key-value组成的数组。 第三个函数接受一个key,断言渲染的时候不存在某个key值的模板变量。 针对上面的例子,我们可以这么断言: ~~~ visit('/index/index/index')->assertViewHas('name','c7'); } } ~~~
';

对响应状态断言

最后更新于:2022-04-02 00:33:29

一个请求发送出去之后,我们可以对HTTP的状态码做出断言,在TP单元测试扩展中对状态码做出响应主要有两个方法: 1. assertResponseOk:无参数,单元状态码为200 2. assertResponseStatus:接受一个状态码作为参数,并对这个状态码直接断言 # assertResponseOk 在快速入门的编写一个简单的测试用例中,我们只有两个测试类,一个是我们编写的,一个是安装扩展的时候自带的。只有两个测试类并且各自只有一个测试方法,理论上只有两个断言,但是却有两个测试类,四个断言。这是因为在单元测试扩展中,当我们构建一个请求的时候,扩展会使用本方法进行断言。 # assertResponseStatus 接受一个参数,该参数是要断言的状态码。 assertResponseOk内部便是使用该方法进行断言的。 # 例子 注意如果要使用redirect的话,就需要让控制器继承think\Controller。 ~~~ redirect('http://www.baidu.com',302); } } ~~~ 针对上面的控制器进行测试: ~~~ visit('/index/index/index')->assertResponseOk(); } public function testNo(){ $this->visit('/index/index/index2')->assertResponseStatus(200); } } ~~~ >注意,这里的testNo应该是断言200的。在TP扩展中,assertResponseStatus目前阶段基本没有什么用处。因为当发生302的时候,扩展框架会重新就转移地址重新发起一个请求。因此上文中的转移到百度的页面,实际上还是会被重新转发到TP的App::run中,因此返回的结果会是test。例子如下: ~~~ public function testNo(){ $response=$this->visit('/index/index/index2'); $response->assertResponseStatus(200);//不是302 $response->see('test');//OK } ~~~ # 对异常断言 当程序使用AOP来实现权限认证的时候,有可能当用户没有登录的时候,会返回401错误。但是在TP测试框架中,非200的状态码都会抛出一个异常,因此我们可以通过断言异常来判断权限认证: ``` /** * @expectedException think\testing\HttpException */ public function testDeleteUser_noLogin(){ $this->visit('/admin/test/test');//由于用户没有登录,会返回401,而TP测试框架会抛出异常 } ```
';

对session进行断言

最后更新于:2022-04-02 00:33:27

# 说明 因为HTTP协议是无状态的,因此在网站开发的过程中我们经常使用session保存用户信息。 在ThinkPHP的单元测试扩展中,我们是可以对session做出断言的。 在该测试扩展中,对session断言的涉及到两个方法: ~~~ 1. assertSessionHas($key, $value = null) 2. assertSessionHasAll(array $bindings) ~~~ 第一个方法是断言session中是否有保存某个key,其值对应value。当只提供一个参数的时候,只判断session是否存在key,而不判断其值。 第二个方法是对key值数组进行判断。 # 例子 下面给出一个例子,用于测试session的两个方法: ~~~ visit('/index/index/addOneValue'); $response->assertSessionHas('value1'); $response->assertSessionHas('value1',1); } public function testAddTwoValue(){ $sessData=array( 'value2'=>2, 'value3'=>3 ); $response=$this->visit('/index/index/addTwoValue'); $response->assertSessionHas($sessData); } } ~~~
';

构建请求

最后更新于:2022-04-02 00:33:25

# 说明 在TP单元测试扩展中,模拟发送请求可以有5种方法,其中四种是扩展中自带的,另外一种是由我们自己通过request构建一个请求。扩展中带的四中分别是: 1. visit:发起一个GET的请求,只需要传入URI即可 2. submitForm: 3. makeRequest: 4. makeRequestUsingForm: # visit visit方法只接受一个参数uri,在这个参数传入我们的请求路径,扩展便会帮助我们构建一个GET的请求。其在底层是使用方法makeRequest进行构建的。 例子: `$this->visit('/index/index/index');` # makeRequest $method:传输的方法 $uri $parameters = []:所带参数 $cookies = [] $files = [] `$this->makeRequest('GET','/index/index/getMethod/name/c7')` > 注意:请不要使用$parameters进行传参和使用?key=value方式传参,在目前的5.x中,这两种方式都会出现问题。这是因为在CLI下,创建请求的时候$_GET不会被设置,而普通的URL方式在5.X版本又不支持,因此才会出现这个问题的。解决方法是在request::create中添加一行代码:$_GET=$params;但是这个会修改到源代码,因此还是希望大家暂停使用这两种方法,等待官方的解决方案。 > 当使用$parameters进行传参的时候,如果是使用官方封装的request对象来获得参数,程序能够正常运行。但是切记不可使用$_GET等等超全局变量。 # submitForm submitForm是基于makeRequest的,也就是说当使用makeRequest返回的内容中存在Form的话,我们就可以通过submitForm处理这个Form。 因此,我们需要构建两个操作,一个用于返回一个含有form的页面,一个用于接受这个form的请求。 index控制器如下: ~~~
html; } public function testForm(){ return 'hello'; } } ~~~ 可以使用以下测试: ~~~ visit('index/index/index')->submitForm('submit',[ 'test'=>'test' ])->see('hello'); } } ~~~ 首先是使用visit发起一个请求,返回一个带有form的页面。接着使用submitForm提交该form。 ~~~ 注意:这里依然是cli模式下,而通过submitForm依然会使用makeRequest的$parameters参数,因此也会造成在实际的控制器中无法得到具体的参数值。除非使用官方封装的request对象。 ~~~ submitForm接受三个值,从上面的例子中我们可以知道,第一个参数是form的提交按钮的文本,第二个为提交的键值对,第三个为要上传的文件。 # makeRequestUsingForm submitForm是对makeRequestUsingForm的另外一层封装。因此通常使用submitForm会比较方便。如果要使用makeRequestUsingForm的话,我们则需要传入两个参数,一个是Form类型的,一个是提交的文件。 其中Form我们可以自行构建,也可以通过getForm来实现跟submitForm一致的功能。
';

初级教程

最后更新于:2022-04-02 00:33:22

[构建请求](2.%E5%88%9D%E7%BA%A7%E6%95%99%E7%A8%8B/1.%E6%9E%84%E5%BB%BA%E8%AF%B7%E6%B1%82.md) [对session进行断言](2.%E5%88%9D%E7%BA%A7%E6%95%99%E7%A8%8B/2.%E5%AF%B9session%E8%BF%9B%E8%A1%8C%E6%96%AD%E8%A8%80.md) [对响应状态断言](2.%E5%88%9D%E7%BA%A7%E6%95%99%E7%A8%8B/3.%E5%AF%B9%E5%93%8D%E5%BA%94%E7%8A%B6%E6%80%81%E6%96%AD%E8%A8%80.md) [对模板变量进行断言](2.%E5%88%9D%E7%BA%A7%E6%95%99%E7%A8%8B/4.%E5%AF%B9%E6%A8%A1%E6%9D%BF%E5%8F%98%E9%87%8F%E8%BF%9B%E8%A1%8C%E6%96%AD%E8%A8%80.md) [seeXX断言系列](2.%E5%88%9D%E7%BA%A7%E6%95%99%E7%A8%8B/5.seeXX%E6%96%AD%E8%A8%80%E7%B3%BB%E5%88%97.md) [对网页进行断言](2.%E5%88%9D%E7%BA%A7%E6%95%99%E7%A8%8B/6.%E5%AF%B9%E7%BD%91%E9%A1%B5%E8%BF%9B%E8%A1%8C%E6%96%AD%E8%A8%80.md) [对数据库进行断言](2.%E5%88%9D%E7%BA%A7%E6%95%99%E7%A8%8B/7.%E5%AF%B9%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9B%E8%A1%8C%E6%96%AD%E8%A8%80.md) [使用测试套件](2.%E5%88%9D%E7%BA%A7%E6%95%99%E7%A8%8B/9.%E4%BD%BF%E7%94%A8%E6%B5%8B%E8%AF%95%E5%A5%97%E4%BB%B6.md) [使用PHPUNIT断言](2.%E5%88%9D%E7%BA%A7%E6%95%99%E7%A8%8B/10.%E4%BD%BF%E7%94%A8PHPUNIT%E6%96%AD%E8%A8%80.md)
';

如何在3.X中测试

最后更新于:2022-04-02 00:33:20

# 如何在3.x中进行测试 * * * * * ThinkPHP 3.X不同于5.X,由于设计上的原因,使其很难进行单元测试(即对单元测试不友好)。因此如果需要在3.X版本中进行测试的话,可以使用下面的库: [3.X测试扩展库](https://github.com/CODE7070/TPUNIT) 该库的原理是模拟5.x版本,首先定义一个base.php文件,该文件在5.0中是会定义一些常量, 并且注册一个自动导入的方法。两种测试扩展是不一样的。 1. 原理不一样: 前者是模拟发送请求 后者是建立TP基境 2. 粒度不一样: 前者的最小单元为操作。 后者的最小单元是方法。 > 注意:本手册所讲的所有用例只适应ThinkPHP 5.X版本,不适合3.X。不过上面的这个库在TP5.X中也是可以使用的,如果想要在较小的单元上面进行测试,推荐使用上面的扩展库。
';

测试规范

最后更新于:2022-04-02 00:33:18

# 测试规范 * * * * * 通常在ThinkPHP中进行单元测试需要遵守以下的规范: 1. 测试类保存在tests目录下 2. 针对某个控制器的测试类命名规则为xxxTest.php,比如针对Index控制器进行测试的话,则测试的命名为:IndexTest.php 3. 测试类通常继承自TestCase,命名空间通常为tests。 4. 针对某个操作的测试通常命名为testxxx,比如针对Index控制器下的index操作,其测试方法命名为:testIndex,并且需要为公有方法(public)。 5. 建议:当对同一个操场进行多种测试的时候,测试方法的命名可以在尾部递增数字,然后使用注释进行说明,而不用去想具体的测试范围所对应的名字。比如testIndex1,testIndex2. 以下是一个为被测试代码: ~~~ visit('/index/index/test')->see('Hello world!',TRUE); } } ~~~
';

编写一个简单的测试用例

最后更新于:2022-04-02 00:33:16

# 编写一个操作 * * * * * 首次运行ThinkPHP之后,都会默认创建一个Index模块,Index控制器和一个index的操作。 接下来的这个实例,我们就是要在Index控制器中添加一个test的操作,在这个操作中,我们输出一段字符串:`hello world`。然后在测试用例中对这个字符串进行断言。 1. 新建一个test的操作 首先在路径tp5/application/index/controller/Index.php中新建一个test的操作: ~~~ 安全提示:官方建议的根目录应该为public,在这里因为我本地测试项目比较多,因此本项目只是一个子项目,没有设置public为根目录。请不要在生产环境上使用类似上面的路径。 > > 并且因为测试框架是模拟请求,因此是不用搭建服务器的。 2. 新建一个测试用例类 在tests目录下新建一个IndexTest.php的测试用例类,并在其中键入一下的代码: ~~~ visit('/index/index/test')->see('Hello world!'); } } ~~~ > 如果直接复制上面代码,请注意缩进的问题和编码问题。否则运行过程中可能会报错。 该测试用例是继承ThinkPHP单元测试扩展类TestCase的。该类提供了多个用于支持ThinkPHP进行单元测试的方法。 其中,visit方法是接受一个作为URI的参数模拟向ThinkPHP框架中的某个测试发起请求。 而see方法则是断言输出的结果是否符合一个正则表达式,其中第一个参数为要匹配的正则表达式,第二个参数的值为true时断言正则表达式不出现在结果中,为false时断言正则表达式出现在结果中,默认为false。 3. 运行测试 输入一下命令,进行测试: `php think unit` 这条命令需要在ThinkPHP根目录下运行,在本文档中是tp5目录下运行。当在使用命令的时候,需要切换到该目录中来。 think是在ThinkPHP目录下的一个PHP文件,当运行这条命令的时候,实际上会执行think文件的。 这个时候运行结果会是: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/f2333a780f5013fa8da4b49cbb99c215_520x157.jpg) 在结果的最后一行中,显示OK,说明所有的测试用例都测试通过了,在括号中的内容是表示有2个测试用例类,4个断言被测试了。 > 这里之所以有`2 tests`是因为tests目录下还有一个`ExampleTest.php`的测试类。 > > 而`4 assertions`则表明是有四个测试用例。当我们把 > > `$this->visit('/index/index/test')->see('Hello world!');` > > 修改成 > > `$this->visit('/index/index/test');` > > 可以发现,现在的assertions只剩下三个了。因此,可以得知visit内部也有断言。 > > $this->assertEquals(200, $status); > > 主要是对网页请求的状态码进行断言。
';

安装单元测试扩展

最后更新于:2022-04-02 00:33:13

# 使用composer安装ThinkPHP * * * * * 在官方手册中,有三种方法可以下载安装thinkphp 5.x。分别是 1. 直接从官方网站下载 2. 使用git进行下载 3. 使用composer进行安装。 在这里推荐使用第三种,即使用composer进行安装。 ## 使用composer进行安装 1. 安装composer window下直接使用composer的安装程序,下面是下载链接: [点击下载window下的composer安装程序](https://getcomposer.org/Composer-Setup.exe) 类linux下的话直接使用下面命令进行安装: ~~~ curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composer ~~~ 2. 下载ThinkPHP ~~~ composer create-project topthink/think tp5 --prefer-dist ~~~ 3. 安装单元测试扩展 到了这一步,我们的ThinkPHP已经下载好了,接下来就是下载ThinkPHP的单元测试扩展了。 `composer require topthink/think-testing` 这一过程会比较慢,因为PHPUNIT依赖的包比较多,所以下载的时间比较慢。 > 前一步创建的目录是tp5,因此需要切换到tp5目录下运行这一条指令哦。 > > linux: cd tp5 > > windows: cd tp5 4. 进行单元测试 进行上面的那些步骤之后,在tp5目录下,就会多出一个tests的目录和phpunit.xml的文件了。然后我们再运行下面的命令,测试一下安装是否成功: `php think unit` 如果出现下面的信息,则说明安装成功: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/a2cb59dabe41bbaafc03f83e38174aa2_486x139.jpg) 到了这里,你的环境以及配置成功,可以进行下一步了。
';

序言

最后更新于:2022-04-02 00:33:11

# 序言 * * * * * 千盼万盼,在ThinkPHP 5.X中终于支持单元测试了,一举解决了TP进行单元测试的难题。这对使用TP进行开发的项目是有很大的意义,这不仅会提高软件质量,同时也方便项目进行大胆重构优化现有问题。这理应是TP的一个里程碑事件,然而从TP 5.X正式版上线以来,TP社区好像并不是那么重视单元测试这一块。作为一名TP爱好者同时又对测试方面有着浓厚的兴趣,因此着手编写此文档希望能够对TP单元测试的发展有所帮助。 本手册的编写目的主要是为了方便大家了解TP,并且能够指引大家在实际项目中使用单元测试,更甚至能够将测试驱动应用到实际项目当中。 > 如何为本文档进行贡献: 对于那些了解单元测试的,并且支持TP发展欢迎联系作者或者提交到github上面来,继续为本文档贡献文章。首先更新到[github](https://github.com/CODE7070/TPUNIT_Doc)上,之后再同步到看云。 联系QQ:707039333 > 如果你觉得本文档对你有帮助,请点击github右上角的星星,给文档一个肯定。 # 目录 * * * * * * [快速入门](快速入门.md) * [序言](序言.md) * [安装单元测试扩展](安装单元测试扩展.md) * [编写一个简单的测试用例](编写一个简单的测试用例.md) * [测试规范](测试规范.md) * [如何在3.X中测试](如何在3.X中测试.md) * [初级教程](初级教程.md) * [构建请求](构建请求.md) * [对session进行断言](对session进行断言.md) * [对响应状态断言](对响应状态断言.md) * [对模板变量进行断言](对模板变量进行断言.md) * [seeXX断言系列](seeXX断言系列.md) * [对网页进行断言](对网页进行断言.md) * [对数据库进行断言](对数据库进行断言.md) * [使用PHPUNIT断言](使用PHPUNIT断言.md) * [原理](原理.md) * [测试的运行流程](测试的运行流程.md) # 地址 * * * * * 推荐一个高级php同事的公众号:编程说 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/35c247d04677a5a8e2056920b9c93cdd_258x258.jpg) 扫码可以关注 [看云](http://www.kancloud.cn/code7/tpunit) [github](https://github.com/CODE7070/TPUNIT_Doc)
';

快速入门

最后更新于:2022-04-02 00:33:09

[序言](1.%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8/1.%E5%BA%8F%E8%A8%80.md) [安装单元测试扩展](1.%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8/2.%E5%AE%89%E8%A3%85%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E6%89%A9%E5%B1%95.md) [编写一个简单的测试用例](1.%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8/3.%E7%BC%96%E5%86%99%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B.md) [测试规范](1.%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8/4.%E6%B5%8B%E8%AF%95%E8%A7%84%E8%8C%83.md) [如何在3.X中测试](1.%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8/5.%E5%A6%82%E4%BD%95%E5%9C%A83.X%E4%B8%AD%E6%B5%8B%E8%AF%95.md)
';