功能测试

测试驱动开发系列文章的最后一篇文章是关于功能测试的,现在的流行的架构是前后端分离所以很多时候我们并不会像文章里写的那样对响应页面进行功能测试,之前这个系列里的第一篇文章有讲如何对API进行功能测试。

原文链接:https://medium.com/@jsdecena/...

以下是译文:

之前的文章讲述了如何在Laravel中进行正向单元测试和反向单元测试,这篇文章让我们看看在Laravel中如何做功能测试。功能测试会访问控制器中的方法然后断言响应是否正确。

我仍将使用之前文章用的Carousel例子,对他进行功能测试。

创建carousel功能测试

在对你的项目进行功能测试的时候,一定要确保管理后台的功能测试要与前台的功能测试隔离开来。在本例中,我通过命名空间AdminFront来分离管理后台的测试和前端页面的测试。

现在让我们专注于管理后台carousel的CRUD功能测试。在test/Feature目录里添加CarouselFeatureTest 类。

<?php
namespace Tests\Feature\Admin\Carousels;
use Tests\TestCase;
class CarouselFeatureTest extends TestCase
{/** @test */public function it_can_show_the_create_carousel_page(){$employee = factory(User::class)->create();$this->actingAs($employee, 'admin')->get(route('admin.carousel.create'))->assertStatus(200)->assertSee('Title')->assertSee('Subtitle')->assertSee('Link')->assertSee('Link Text')->assertSee('Image');}
}

我们来分析一下上面的代码。

  • 我们需要->actingAs()方法来通过用户认证中间件并且模拟admin用户(如果项目中没有进行使用认证看守器则不需要这一步)。
  • 然后我们通过route()取出了创建carousel的页面。
  • 断言响应的HTTP状态码为200
  • 最后断言会在页面上看到的文本值。

运行phpunit看看会发生什么。

PHPUnit 6.5.7 by Sebastian Bergmann and contributors.
E                                                                   1 / 1 (100%)
Time: 920 ms, Memory: 26.00MB
There was 1 error:
1) Tests\Feature\Admin\Carousels\CarouselFeatureTest::it_can_show_the_create_carousel_page
InvalidArgumentException: Route [admin.carousel.create] not defined.

出错就对了。我们还没有在web.php这个路由文件中定义路由,所以将会出现上面的错误。让我们定义这个路由。

<?php
Route::namespace('Admin')->group(function () {Route::resource('carousel', 'Carousels\CarouselController');
});

分析:

  • 在我的app/Http/Controllers目录中还有其他目录归置文件和文件夹。我有Admin, FrontAuth这几个目录。
  • Admin这个命名空间中还有Carousels文件夹,在这个文件夹中是CarouselController.php文件。

在终端中运行中运行如下命令来创建控制器

php artisan make:controller --resource Admin/Carousels/CarouselController

定义路由、创建好Controller之后,再次运行phpunit

PHPUnit 6.5.7 by Sebastian Bergmann and contributors.
F                                                                   1 / 1 (100%)
Time: 987 ms, Memory: 28.00MB
There was 1 failure:
1) Tests\Feature\Admin\Carousels\CarouselFeatureTest::it_can_show_the_create_carousel_page
Failed asserting that '' contains "Title".

起作用了!路由错误消失了不过我们遇到了一个新的错误,通过新错误让我们想到应该是测试用例服务在响应的UI页面上找到Title这个单词。Hmm 好吧,这是应为我们没有在create方法中返回视图,让我们加上返回视图的代码。

<?php
namespace App\Http\Controllers\Admin\Carousels;
use App\Http\Controllers\Controller;
class CarouselController extends Controller
{/*** @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View*/public function create(){return view('admin.carousels.create');}
}

视图文件位于resource/views/admin/carousels/create.blade.php

@extends('layouts.admin.app')@section('content')<!-- Main content --><section class="content">@include('layouts.errors-and-messages')<div class="box"><div class="box-body"><form action="{{ route('admin.carousel.store') }}" method="post" enctype="multipart/form-data">{{ csrf_field() }}<div class="form-group"><label for="title">Title</label><input type="text" name="title" id="title" class="form-control" placeholder="Title" value="{{ old('title') }}"></div><div class="form-group"><label for="image">Image</label><input type="file" name="image" id="image" class="form-control"></div><div class="form-group"><label for="link">Link</label><div class="input-group"><span class="input-group-addon">http://</span><input type="text" name="link" id="link" class="form-control" placeholder="www.example.com" value="{{ old('link') }}"></div></div><div class="btn-group"><a href="{{ route('admin.carousel.index') }}" class="btn btn-default btn-sm">Back</a><button type="submit" class="btn btn-primary btn-sm">Create</button></div></form></div></div></section><!-- /.content -->
@endsection

视图文件夹中并没有admincarousels文件夹,所以你需要自己创建它们。

创建好blade视图文件后再次运行phpunit

➜  git: phpunit --filter=CarouselFeatureTest::it_can_show_the_create_carousel_page
PHPUnit 6.5.7 by Sebastian Bergmann and contributors.
.                                                                   1 / 1 (100%)
Time: 810 ms, Memory: 28.00MB
OK (1 test, 6 assertions)

Nice,看起来非常好。

现在,如果有人搞乱了你的blade模板,你会马上知道因为这个测试会执行失败。到Github里去检查一下到底是谁搞乱模板文件,蛤!

通过POST数据创建carousel

现在让我们测试一下通过页面里的表单是否能够创建carousel数据。

要创建carousel别忘了先写测试,没有捷径。

<?php
namespace Tests\Feature\Admin\Carousels;
use Tests\TestCase;
class CarouselFeatureTest extends TestCase
{/** @test */public function it_can_create_the_carousel(){$file = UploadedFile::fake()->create('image.jpg');$data = ['title' => $this->faker->word,'link' => $this->faker->url,'image' => $file,];$employee = factory(User::class)->create();$this->actingAs($employee, 'admin')->post(route('admin.carousel.store'), $data)->assertStatus(302)->assertRedirect(route('admin.carousel.index'))->assertSessionHas('message', 'Create carousel successful!');}/** @test */public function it_can_show_the_create_carousel_page(){$employee = factory(User::class)->create();$this->actingAs($employee, 'admin')->get(route('admin.carousel.create'))->assertStatus(200)->assertSee('Title')->assertSee('Subtitle')->assertSee('Link')->assertSee('Link Text')->assertSee('Image');}
}

分析:

  • 我们断言在创建成功后会重定向到carousel列表页。
  • 我们还断言成功设置了Create carousel successful!这个Flash信息

这个测试会执行失败,因为store()方法现在还空着,让我们用下面的代码填充它:

<?php
namespace App\Http\Controllers\Admin\Carousels;
use App\Http\Controllers\Controller;
use App\Shop\Carousels\Exceptions\CarouselNotFoundException;
use App\Shop\Carousels\Exceptions\CreateCarouselErrorException;
use App\Shop\Carousels\Exceptions\UpdateCarouselErrorException;
use App\Shop\Carousels\Repositories\CarouselRepository;
use App\Shop\Carousels\Repositories\CarouselRepositoryInterface;
use App\Shop\Carousels\Requests\CreateCarouselRequest;
use App\Shop\Carousels\Requests\UpdateCarouselRequest;
use Illuminate\Http\UploadedFile;
class CarouselController extends Controller
{/*** @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View*/public function create(){return view('admin.carousels.create');}/*** @param CreateCarouselRequest $request* @return \Illuminate\Http\RedirectResponse*/public function store(CreateCarouselRequest $request){try {$data = $request->except('_token');if ($request->hasFile('image') && $request->file('image') instanceof UploadedFile) {$data['src'] = $request->file('image')->store('carousels', ['disk' => 'public']);}$carouselRepo = new CarouselRepository(new Carousel);$carouselRepo->createCarousel($data);$request->session()->flash('message', 'Create carousel successful!');return redirect()->route('admin.carousel.index');} catch (CreateCarouselErrorException $e) {$request->session()->flash('error', $e->getMessage());return redirect()->back()->withInput();}}
}

然后运行phpunit

➜  git: phpunit --filter=CarouselFeatureTest::it_can_create_the_carousel
PHPUnit 6.5.7 by Sebastian Bergmann and contributors.
.                                                                   1 / 1 (100%)
Time: 993 ms, Memory: 28.00MB
OK (1 test, 5 assertions)

在编写其他控制器方法时也像这样写功能测试,准备好出发吧。

Laravel测试驱动开发--功能测试 1相关推荐

  1. Laravel测试驱动开发--功能测试

    功能测试 测试驱动开发系列文章的最后一篇文章是关于功能测试的,现在的流行的架构是前后端分离所以很多时候我们并不会像文章里写的那样对响应页面进行功能测试,之前这个系列里的第一篇文章有讲如何对API进行功 ...

  2. Laravel测试驱动开发 -- 正向单元测试

    上一篇翻译的文章里通过简单的十一步讲述了如何在Laravel中进行测试驱动开发,这是作者关于测试的第二篇文章, 文章中简述了如何在Laravel中进行增删改查的单元测试,本文中的单元测试都是正向测试, ...

  3. Laravel测试驱动开发--反向单元测试

    Negative CRUD Unit Testing in Laravel5 这是一篇译文,原文链接: https://medium.com/@jsdecena/... 作为CRUD Unit Tes ...

  4. Laravel测试驱动开发--反向单元测试 1

    Negative CRUD Unit Testing in Laravel5 这是一篇译文,原文链接: https://medium.com/@jsdecena/... 作为CRUD Unit Tes ...

  5. rest laravel_如何通过测试驱动开发来构建Laravel REST API

    rest laravel by Kofo Okesola 由Kofo Okesola 如何通过测试驱动开发来构建Laravel REST API (How to build a Laravel RES ...

  6. Python 测试驱动开发读书笔记(一)使用功能测试协助安装Django

    使用功能测试协助安装Django 本章节知识分为两部分 一是测试驱动开发(Test-Driven Development,TDD)的基础知识: 二是从零开始写一个Web的应用,并用Selenium进行 ...

  7. 测试驱动开发 测试前移_测试驱动的开发可能看起来是工作的两倍-但无论如何您都应该这样做...

    测试驱动开发 测试前移 by Navdeep Singh 通过Navdeep Singh 测试驱动的开发可能看起来是工作的两倍-但无论如何您都应该这样做 (Test-driven developmen ...

  8. 测试驱动开发 测试前移_测试驱动陷阱,第2部分

    测试驱动开发 测试前移 单元测试中单元的故事 在本文的上半部分 ,您可能会看到一些不好但很受欢迎的测试示例. 但是我不是一个专业的批评家(也被称为"巨魔"或"仇恨者&qu ...

  9. 测试驱动开发_DevOps之浅谈测试驱动开发

    "测试驱动开发(Test-Driven Development, TDD),以测试作为开发过程的中心,它要求在编写任何产品代码之前,先编写用于定义产品代码行为的测试,而编写的产品代码又要以使 ...

最新文章

  1. LTE voice centric和data centric
  2. android ui自动化测试工具,介绍Robotium+Orange实现androidUI自动化测试
  3. 错误处理笔记 导入 torch.utils.tensorboard时 找不到tensorboard
  4. numpy.negative详解
  5. 升级安装linux ssh 升级安装
  6. 从php+mysql环境的注入,到整台服务器的沦陷
  7. C# 异步方法的异常处理
  8. slf4j日志的最优使用方式
  9. c++使用单向链表存储一组有序数据_初试攻略丨计算机考研中数据结构知识点总结,硬核!...
  10. Hadoop伪分布式集群的安装部署
  11. 神经网络之预测共享单车使用情况
  12. C++添加一个头文件和extern以及全局变量和局部变量问题(清C++蓝书16.3.19上机的一小题)...
  13. 用where导致group by分组字段的索引失效
  14. 客车网上订票系统项目--在线预约、个人中心我的订单
  15. 中国经济社会大数据研究平台——国内统计数据
  16. 镀镍金刚石线切割硅片
  17. GPIO设备虚拟文件结点的创建【转】
  18. 中国气象台API(2017.09)
  19. 【QT项目】简易五子棋游戏(人机对战)— 完整源码
  20. 收发EtherCAT帧——ecx_srconfirm函数

热门文章

  1. day12【过渡】SpringCloud
  2. 第 12 章 多路查找树
  3. mysql 8.0 安装_安装MySQL-8.0.19
  4. 计算机开机和关机的音乐,电脑开关机音乐设置
  5. dns文件传输服务器,MOOC云计算 - DNS三部曲之DNS区域传输限制
  6. html点线面制作,利用HTML5绘制点线面组成的3D图形的示例_html5教程技巧
  7. 第一个java程序的错误_我是一名java初学者,执行第一个java程序welcome.java出现了以下错误,这是为什么?...
  8. springboot templates读取不到_精通 Spring Boot 系列 04
  9. linux防火墙多个 多个ip配置,iptables一次性封多个ip,使用ipset 工具
  10. 计算机键盘换挡键,电脑键盘上的换挡键是哪个