基于 Laravel 开发博客应用系列 —— 从测试开始(二):使用Gulp实现自动化测试
3、使用 Gulp 进行 TDD(测试驱动开发)
Gulp 是一个使用 JavaScript 编写的自动化构建工具。用于对前端通用任务(如最小化、压缩、编译)进行自动构建。Gulp 还可以用来监控源代码的改动并自动运行任务。
Laravel 5.1 提供了一个封装 Gulp 的 Laravel Elixir 包,可用于轻松构建 Gulp 任务,Elixir 为 Gulp 添加了优雅的语法,Elixir 之于 Gulp 正如 Laravel 之于 PHP。
Gulp 最常见的用法之一就是自动构建单元测试,这里我们将遵循 TDD(测试驱动开发)流程让 Gulp 自动运行测试。
首先,编辑根目录下的 gulpfile.js
文件如下:
var elixir = require('laravel-elixir'); elixir(function(mix) {
mix.phpUnit();
});
这里我们调用 elixir()
方法,接收的 mix
对象可以用于处理很多事情。你可以用它来将 LESS 文件编译成 CSS 文件,也可以用它来将多个 CSS 文件合并到一起,并且为合并后的文件添加版本控制,等等等等。所有这些事情都可以通过调用 mix
对象提供的接口方法来实现。
但是现在,我们只运行 PHPUnit 测试。
接下来,在本地主机的项目根目录下,运行 gulp
来看看会发生什么:
你应该还会接收到一个弹出框通知,通知如果是绿色的表明测试成功:
如果想让 gulp
进入自动进行单元测试模式,需要在本地主机的命令行中使用 gulp tdd
命令:
如果Ubuntu下执行该命令报错:Error: watch ENOSPC,对应解决办法是在终端执行如下命令:
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
再重新运行 gulp tdd
即可。
运行 gulp tdd
命令后该命令会一直挂起在那里,监听源文件的修改,并在需要的时候运行单元测试。
为了演示是否有效,我们修改 tests/ExampleTest.php
中的 see()
这一行测试代码如下:
$this->visit('/')->see('Laravel Academy');
保存这个文件后,gulp
将会接到通知并再次运行单元测试。这一次运行测试失败,并会看到类似下面这样的失败提示框:
撤销 tests/ExampleTest.php
中的修改并保存,gulp
会再次运行 PHPUnit,这一次又可以接收到测试成功通知。
注:要退出 Gulp 的 tdd 模式只需使用快捷键 Ctrl+C 即可。
4、创建Markdown服务
在本博客项目中我们将使用 Markdown 格式编辑文章。Markdown 是一种轻量级的标记语言,Markdown 的理念是能让文档更容易读、写和随意改。Markdown 格式文本可以被轻松转化为 HTML。
为了举例进行测试,我们将要使用 TDD 开发流程构建将 Markdown 文本转化为 HTML 文本的服务。
安装 Markdown 依赖包
有很多 PHP 包可用于将 Markdown 转化为 HTML。这里我们使用 Michel Fortin 提供的包 SmartyPants,在本地主机上使用 Composer 安装下面两个依赖包:
nonfu@ubuntu:~/Code/blog$ composer require michelf/php-markdown
nonfu@ubuntu:~/Code/blog$ composer require "michelf/php-smartypants=1.6.0-beta1"
创建 Markdown 测试类
开启 TDD 首先要做的事情就是触发 gulp 为 tdd 模式(如果已经开启略过此步):
nonfu@ubuntu:~/Code/blog$ gulp tdd
现在 Gulp 已经在监听文件修改,一旦有“风吹草动”,就会立即运行 PHPUnit。
下面我们来创建测试类。在 tests
目录中创建一个 Services
文件夹,并在该文件夹下新建一个MarkdownerTest.php
,编辑文件内容如下:
<?php class MarkdownerTest extends TestCase
{ protected $markdown; public function setup()
{
$this->markdown = new \App\Services\Markdowner();
} public function testSimpleParagraph()
{
$this->assertEquals(
"<p>test</p>\n",
$this->markdown->toHTML('test')
);
}
}
保存文件后,你应该会接收到测试失败通知。
这里需要说明的是,尽管测试有时候会失败,但有时候这也是件好事情,因为通过失败信息可以推断哪里出错了,从而方便我们迅速解决问题。此时错误的原因是 App\Services\Markdowner
这个类不存在。
创建Markdowner服务
这里我们创建一个封装前面使用 Composer 安装的 php-markdown
和 php-smartypants
包的简单服务类。
在 app\Services
目录下新建 Markdowner.php
文件,编辑该文件内容如下:
<?php namespace App\Services; use Michelf\MarkdownExtra;
use Michelf\SmartyPants; class Markdowner
{ public function toHTML($text)
{
$text = $this->preTransformText($text);
$text = MarkdownExtra::defaultTransform($text);
$text = SmartyPants::defaultTransform($text);
$text = $this->postTransformText($text);
return $text;
} protected function preTransformText($text)
{
return $text;
} protected function postTransformText($text)
{
return $text;
}
}
保存该文件后,Gulp 检测到文件修改然后重新运行单元测试,这次会就收到绿色的提示,代表测试通过,一切正常。
如果没有看到绿色提示,则代表测试失败,需要回头检查下 App\Services\Markdowner
和 MarkdownerTest
这两个类看是否有什么问题。
更加复杂的迭代测试
诚然,这并不是 TDD 的最佳示例,因为这只是先创建一个简单的测试类,然后创建实现类修复测试出现的问题。在实际应用场景中,TDD 应该有更多次的迭代,其大致流程应该像这样:
- 创建
MarkdownerTest
,定义测试方法 - 测试失败
- 创建
Markdowner
类,硬编码toHTML()
进行测试 - 测试成功
- 修改
Markdowner
类使用MarkdownExtra
- 测试成功
- 添加
testQuotes()
方法到MarkdownerTest
类 - 测试失败
- 修改
Markdowner
类使用SmartyPants
- 测试成功
以此类推。甚至 Markdowner
类的结构都是有缺陷的,要对该类进行纯正的单元测试,应该将 MarkdownExtra
和 SmartyPants
的实例注入到 Markdowner
的构造函数中,这样的话我们的单元测试可以注入模拟的对象并且只验证 MarkdownExtra
的行为而不是其调用的类。
但是本系列教程不是关于测试的,实际上,我们只会在这里讨论测试,我们仍将保留其结构但是会添加更多的测试。
修改 MarkdownerTest.php
文件内容如下:
<?php class MarkdownerTest extends TestCase
{ protected $markdown; public function setup()
{
$this->markdown = new \App\Services\Markdowner();
} /**
* @dataProvider conversionsProvider
*/
public function testConversions($value, $expected)
{
$this->assertEquals($expected, $this->markdown->toHTML($value));
} public function conversionsProvider()
{
return [
["test", "<p>test</p>\n"],
["# title", "<h1>title</h1>\n"],
["Here's Johnny!", "<p>Here’s Johnny!</p>\n"],
];
}
}
这里我们修改测试类同时进行多个转化测试。
5、其它测试方法
这里我们不想列出 Laravel 5.1 中所有可用的测试方法,因为PHP中的测试方法不是单一的,也不是固定不变的,在 Laravel 中同样也是如此。但是这里,我们还是想要列出一些其它可选的测试方法。
phpspec
除了 PHPUnit 之外,Laravel 5.1还提供了开箱即用的 phpspec。这是另一个流行的 PHP 单元测试工具,聚焦于行为驱动开发(BDD)。
下面是 phpspec 的一些说明:
- 安装在
vendor/bin
目录下,因此可以在项目根目录中直接运行phpspec
- 配置文件是位于项目根目录下的
phpspec.yml
- 要从 Gulp 中运行 phpspec,可以调用
mix
对象上的phpSpec()
函数 - 如果你将应用的命名空间名称
App
改成了其它的,需要修改phpspec.yml
中相应的配置
单元测试
尽管说到 PHP 单元测试,PHPUnit 已经成为事实上的标准方式,但还是有一些其他单元测试包可供使用:
功能测试
这种测试是对整个应用进行测试而不是仅仅验证应用中的某个片段。当使用 Laravel 5.1 提供的测试方法时,还可以使用 PHPUnit 进行一些功能测试。ExampleTest.php
中提供了一个简单的示例,但是还有专门的测试框架专注于功能测试:
行为驱动开发(BDD)
BDD 有两个分支:SpecBDD 和 StoryBDD
SpecBDD 专注于代码的技术层面,Laravel 5.1 自带的 phpspec 是标准的SpecDD
StoryBDD 则强调商业或者功能测试,Behat 是最流行的 StoryBDD 框架,此外,Codeception 也可以用作 StoryBDD。
基于 Laravel 开发博客应用系列 —— 从测试开始(二):使用Gulp实现自动化测试的更多相关文章
- 基于 Laravel 开发博客应用系列 —— 从测试开始(一):创建项目和PHPUnit
1.创建博客项目 我们将遵循上一节提到的六步创建一个新 Laravel 5.1 项目的步骤,创建本节要用到的博客项目 —— blog. 首先,在本地主机安装应用骨架: nonfu@ubuntu:~/C ...
- 基于 Laravel 开发博客应用系列 —— 设置 Windows 本地开发环境
1.安装原生PHP 下载/解压 PHP 到 PHP 下载页下载最新版本的 PHP(如果使用 Laravel 5.1 的话需要 PHP 5.5.9+ 版本),解压下载的zip格式压缩文件到本地目录,比如 ...
- 基于Laravel开发博客应用系列 —— 构建博客后台管理系统
一个完整的博客应用不能没有后台管理系统.所以在本节中我们将继续完善博客应用 —— 开发后台管理系统. 1.创建路由 在上一节十分钟创建博客项目中,已经设置过了 app/Http/routes.php, ...
- 基于 Laravel 开发博客应用系列 —— 项目必备软件安装
1.概述 通过本项目我们将会构建一个简单.清爽.优雅的博客系统,以及维护管理该博客的后台. 本项目源码公开在GitHub上:https://github.com/ChuckHeintzelman/l5 ...
- 基于Laravel开发博客应用系列 —— 使用Bower+Gulp集成前端资源
本节我们将讨论如何将前端资源集成到项目中,包括前端资源的发布和引入.本项目将使用 Bower 和 Gulp 下载和集成jQuery.Bootstrap.Font Awesome 以及 DataTabl ...
- 基于Laravel开发博客应用系列 —— 十分钟搭建博客系统
1.创建文章数据表及其模型(0:00~2:30) 我们已经在上一节中为博客项目完成了大部分准备工作,现在首先要做的就是为这个项目创建一个新的文章表 posts及该表对应的模型类 Post,使用如下Ar ...
- 基于 Laravel 开发博客应用系列 —— 设置 Linux/Mac 本地开发环境
1.不同 Linux 发行版本的区别 不同的 Linux 发行版本之间有一些细微区别,尤其是包管理器:CentOS 和 Fedora 使用 yum 作为包管理器,而Ubuntu 使用 apt,在 O ...
- 基于 Laravel 开发博客应用系列 —— Homestead 和 Laravel 安装器
1.Homestead 从主机操作系统的控制台中(Windows 中被称作命令提示符,Linux 中被称作终端),你可以轻松通过不带参数的homestead 命令查看所有有效的 Homestead 命 ...
- 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 ... 基于. ...
随机推荐
- 2017 清北济南考前刷题Day 4 morning
考场思路: 倒着算就是 可以对一个数-1 可以合并两个数 可以证明只有0和0才能执行合并操作 然后模拟 #include<cstdio> #include<iostream> ...
- 微信网页动画---swiper.animate.css
项目需要,自己写了个demo <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...
- 推荐一些我所用的firefox 附加组件。
firefox之所以强大,很大程度上是因为它有着超多的扩展组件,来实现许多有趣的功能.这几天把我装的firefox附加组件整理下,个人认为是一般上网常用或者可以说是必备的组件,o(∩_∩)o ,晒晒. ...
- soj1046. Plane Spotting
1046. Plane Spotting Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description Craig is fond o ...
- 最长递增子序列(LIS)(转)
最长递增子序列(LIS) 本博文转自作者:Yx.Ac 文章来源:勇幸|Thinking (http://www.ahathinking.com) --- 最长递增子序列又叫做最长上升子序列 ...
- apache服务器yii2报The fileinfo PHP extension is not installed解决思路
这个问题整整困扰了我两天,今天终于搞定了.记录一下. 背景是这样的,我呢,在centos服务器上安装了lamp环境,其中php是5.3.3,在用composer安装yii2的时候,出现了某些yii2插 ...
- 2018 CCPC网络赛
2018 CCPC网络赛 Buy and Resell 题目描述:有一种物品,在\(n\)个地点的价格为\(a_i\),现在一次经过这\(n\)个地点,在每个地点可以买一个这样的物品,也可以卖出一个物 ...
- maven profile 优先级
maven profile是有优先级别 也就是说在setting.xml的profile优先级比pom中同名的profile高. 可以使用 mvn help:active-profiles 这个命令是 ...
- centos7的防火墙(firewalld)
Centos7中默认将原来的防火墙iptables升级为了firewalld,firewalld跟iptables比起来至少有两大好处: 1.firewalld可以动态修改单条规则,而不需要像ipta ...
- irport报表,把数字金额转换成大写人民币金额
1.编写oracle函数 CREATE OR REPLACE Function MoneyToChinese(Money In Number) Return Varchar2 Is strYuan ) ...