标签:arch contents throw run http exist inject available sql
In this chapter we’ll create a project to use throughout the rest of the book and explore various options for testing. Along the way a service class to convert Markdown formatted text files to HTML will be developed.
Following the Six Steps to Starting a New Laravel 5.1 Project from the previous chapter, create the l5beauty project as outlined below.
First, from your Host OS, install the app skeleton.
~/Code % laravel new l5beauty
Crafting application...
Generating optimized class loader
Compiling common classes
Application key [rzUhyDksVxzTXFjzFYiOWToqpunI2m6X] set successfully.
Application ready! Build something amazing.
Next, from within the Homestead VM, set up l5beauty.app
as the virtual host.
~/Code$ serve l5beauty.app ~/Code/l5beauty/public
dos2unix: converting file /vagrant/scripts/serve.sh to Unix format ...
* Restarting nginx nginx [ OK ]
php5-fpm stop/waiting
php5-fpm start/running, process 2169
Back in your Host OS, add the following line to your hosts file.
192.168.10.10 l5beauty.app
From your Host OS, do the step to install the NPM packages locally.
~% cd Code/l5beauty
~/Code/l5beauty% npm install
|
> node-sass@2.0.1 install /Users/chuck/Code/l5beauty/node_modules/laravel- elixir/node_modules/gulp-sass/node_modules/node-sass
> node scripts/install.js
> node-sass@2.0.1 postinstall /Users/chuck/Code/l5beauty/node_modules/ laravel-elixir/node_modules/gulp-sass/node_modules/node-sass
> node scripts/build.js
`darwin-x64-node-0.10` exists; testing
Binary is fine; exiting
gulp@3.8.11 node_modules/gulp
├── v8flags@2.0.2
├── pretty-hrtime@0.2.2
[snip]
Go back within the Homestead VM and create the database for this project.
$ mysql --user=homestead --password=secret
mysql> create database l5beauty;
Query OK, 1 row affected (0.00 sec)
mysql> exit;
Bye
Then edit the .env
file, changing the database to l5beauty
.
// Change the following line
DB_DATABASE=homestead
// To the correct value
DB_DATABASE=l5beauty
Finally, bring up http://l5beauty.app
in your browser to make sure everything is working correctly.
Laravel 5.1 comes out of the box ready for testing. There’s even a very simple unit test supplied to make sure a web request to the application returns the expected 200 HTTP response.
To run PHPUnit, simply execute the phpunit
command from the project’s root directory.
~% cd Code/l5beauty
~/Code/l5beauty% phpunit
PHPUnit 4.7.4 by Sebastian Bergmann and contributors.
.
Time: 544 ms, Memory: 10.25Mb
OK (1 test, 2 assertions)
If you receive a command not found or a permissions denied error when attempting to run the phpunit
command it could be because of an installation bug. The phpunit
command should be found in the vendor/bin
directory—and this directory was added to the path in your Host OS back in Chapter 3 or 4. The problem is that the Laravel command has a bug that doesn’t necessarily set the permissions correctly on phpunit and several other utilities.
To fix this bug, follow the two steps below.
Step 1 - Delete the vendor
directory. Just wipe it out using whatever command is appropriate for your Host OS.
Step 2 - Recreate the vendor
directory using the composer update
command from your project’s root directory. (Do this from your Host Operating System.)
That’s it. Then try executing the phpunit
command again.
In the root of each Laravel 5.1 project is the file phpunit.xml
. This contains the configuration PHPUnit uses when phpunit
is executed from the project’s root directory.
Examination of the phpunit.xml
will show the tests reside within the tests
directory. There are two files located there.
ExampleTest.php
- Contains one test testBasicExample()
. The ExampleTest
class is derived from the TestCase
parent provided in the other file.TestCase.php
- The base class from which to derive Laravel tests.Take a look at the testBasicExample()
method in ExampleTest.php
.
public function testBasicExample()
{
$this->visit(‘/‘)
->see(‘Laravel 5‘);
}
This test says “Visit the home page and we should see the words ‘Laravel 5’.” Can tests get any simpler than this?
The TestCase
class provides additional Laravel 5.1 specific application methods and properties to your unit tests. TestCase
also provides a long list of additional assertion methods and crawler type tests.
The Crawler tests allow you to test pages in your web application. The nice thing is that many of these tests are fluent and return $this
, allowing you to build the ->visit()->see()
type test in the above example.
Here are some of the available properties and methods.
$this->response
$this->currentUri
visit($uri)
get($uri, array $headers = [])
post($uri, array $data = [], array $headers = [])
put($uri, array $data = [], array $headers = [])
patch($uri, array $data = [], array $headers = [])
delete($uri, array $data = [], array $headers = [])
followRedirects()
see($text, $negate = false)
seeJson(array $data = null)
$data
passed, also asserts the JSON value exactly matches.seeStatusCode($status)
seePageIs($uri)
seeOnPage($uri)
and landOn($uri)
seePageIs()
click($name)
type($text, $element)
check($element)
select($option, $element)
attach($absolutePath, $element)
press($buttonText)
withoutMiddleware()
dump()
Here’s a brief rundown of some of the additional application methods and properties Laravel 5.1 provides to PHPUnit.
$app
$code
refreshApplication()
setup()
method.call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
callSecure($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
action($method, $action, $wildcards = [], $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
route($method, $name, $routeParameters = [], $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
instance($abstract, $object)
expectsEvents($events)
withoutEvents()
expectsJobs($jobs)
withSession(array $data)
session(array $data)
flushSession()
startSession()
actingAs($user)
be($user)
seeInDatabase($table, array $data, $connection = null)
notSeeInDatabase($table, $array $data, $connection = null)
missingFromDatabase($table, array $data, $connection = null)
notSeeInDatabase()
.seed()
artisan($command, $parameters = [])
Any of these methods or properties can be accessed within your test classes. The provided ExampleTest.php
file contains a line using $this->call(...)
inside the testBasicExample()
method.
In addition to the standard PHPUnit assertions (such as assertEquals()
, assertContains()
, assertInstanceOf()
, …), Laravel 5.1 provides many additional assertions to help write tests dealing with the web application.
assertPageLoaded($uri, $message = null)
assertResponseOk()
assertReponseStatus($code)
assertViewHas($key, $value = null)
assertViewHasAll($bindings)
assertViewMissing($key)
assertRedirectedTo($uri, $with = [])
assertRedirectedToRoute($name, $parameters = [], $with = [])
assertRedirectedToAction($name, $parameters = [], $with = [])
assertSessionHas($key, $value = null)
assertSessionHasAll($bindings)
assertSessionHasErrors($bindings = [])
assertHasOldInput()
Gulp is a build and automation system written in Javascript. It allows common tasks such as minification of source files to be automated. Gulp can even watch your source code for changes and automatically run tasks when this occurs.
Laravel 5.1 includes Laravel Elixir which allows Gulp tasks to be built in easy ways. Elixir adds an elegant syntax to gulp. Think of it this way … what Laravel is to PHP, Elixir is to Gulp.
One of the most common uses of Gulp is to automate unit tests. We’ll follow the TDD (Test Driven Development) process here and let Gulp automatically run our tests.
First, edit the gulpfile.js
file in the l5beauty
project’s root directory to match what’s below.
var elixir = require(‘laravel-elixir‘);
elixir(function(mix) {
mix.phpUnit();
});
Here we call the elixir()
function, passing a function. The mix
object this function will receive will be a stream on which multiple things can happen. You might want to build LESS files into CSS files here, then concatenate those CSS files together, and then provide versioning on the resulting concatenated files. All of those things can be specified by using a fluent interface on the mix
object.
But for now, we’re only running PHPUnit tests.
Next, from the project root on your Host OS, run gulp to see what happens.
~% cd Code/l5beauty
~/Code/l5beauty% gulp
[15:26:23] Using gulpfile ~/Code/l5beauty/gulpfile.js
[15:26:23] Starting ‘default‘...
[15:26:23] Starting ‘phpunit‘...
[15:26:25] Finished ‘default‘ after 2.15 s
[15:26:25]
*** Debug Cmd: ./vendor/bin/phpunit --colors --debug ***
[15:26:28] PHPUnit 4.7.4 by Sebastian Bergmann and contributors.
Configuration read from /Users/chuck/Code/l5beauty/phpunit.xml
Starting test ‘ExampleTest::testBasicExample‘.
.
Time: 2.07 seconds, Memory: 10.25Mb
OK (1 test, 2 assertions)
[15:26:28] gulp-notify: [Green!]
[15:26:28] Finished ‘phpunit‘ after 4.96 s
You should have received a notification, a popup alert of some sort, on your Host OS. The notification should be green which indicates everything tested successfully.
To have gulp go into automatic mode for unit tests, use the gulp tdd
command in your Host OS.
~% cd Code/l5beauty
~/Code/l5beauty% gulp tdd
[15:29:49] Using gulpfile ~/Code/l5beauty/gulpfile.js
[15:29:49] Starting ‘tdd‘...
[15:29:49] Finished ‘tdd‘ after 21 ms
The command will just hang there, watching for source file changes and running unit tests when needed.
To see how this works, let’s break the existing unit test.
Change the see()
line in tests/ExampleTest.php
to what’s below.
->see(‘Laravel 5x‘);
When you save this file, gulp will notice and run PHPUnit again. The will fail and you will see a notice on your computer similar to the one below.
Change the line back to what it was before, save it, and again gulp will run PHPUnit. This time you should receive a notice indicating you are “back to green”.
Simply press Ctrl+C
The blogging application we’ll be building will allow editing posts in Markdown format. If you aren’t familiar with Markdown, check out the link. It’s an easy-to-read and easy-to-write format that transforms easily to HTML.
To illustrate testing, we’ll build a service to convert markdown text to HTML text using TDD.
There are many PHP packages out there for converting Markdown to HTML. If you go to http://packagist.org
and search for markdown there are twenty pages of packages.
We’ll use the package created by Michel Fortin because there’s another package called SmartyPants
by the same author that converts quotation marks to the nice looking curly quotes.
From your Host OS’s console do the following to pull in the packages.
~/Code/l5beauty% composer require michelf/php-markdown
Using version ^1.5 for michelf/php-markdown
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing michelf/php-markdown (1.5.0)
Downloading: 100%
Writing lock file
Generating autoload files
Generating optimized class loader
~/Code/l5beauty% composer require "michelf/php-smartypants=1.6.0-beta1"
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing michelf/php-smartypants (1.6.0-beta1)
Loading from cache
Writing lock file
Generating autoload files
Generating optimized class loader
Did you notice that the specific version of the package was specified when requiring SmartyPants? This is because at the time of this writing there isn’t a stable package that can be pulled in automatically.
The first thing to do when starting a TDD session is to fire up Gulp in TDD mode.
~/Code/l5beauty% gulp tdd
[19:41:38] Using gulpfile ~/Code/l5beauty/gulpfile.js
[19:41:38] Starting ‘tdd‘...
[19:41:38] Finished ‘tdd‘ after 23 ms
Now that Gulp is watching for changes and ready to run PHPUnit as soon as it detects any, let’s create the test class.
In the tests
directory, create a new folder named Services
and a file called 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‘)
);
}
}
setup()
method create a new instance of the Markdowner
class. (Yes, this doesn’t exist yet.)You should have received a failure notice. (If you didn’t Ctrl+C out of Gulp and restart it.)
Even though a notice appeared saying the test failed, sometimes it’s useful to look at the console to determine what the failure was. In this case, it’s pretty obvious. The App\Services\Markdowner
class doesn’t exist.
What we’ll do here is create a simple service that wraps the php-markdown and php-smartypants packages we imported earlier.
In the app\Services
directory create a Markdowner.php
file with the following contents.
<?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;
}
}
preTransformText()
, but this time if we later want to add our own final transformations.When you save this file, Gulp should notice and you will receive a “GREEN” alert telling you everything worked as expected.
If you don’t receive the green alert, go back and check for typos in both the App\Services\Markdowner
and MarkdownerTest
classes.
Admittedly, this isn’t a great example of TDD because it’s simple a test and a complete class created to fix the test. In actual practice TDD would have many more iterations, resulting in a flow like the one below:
And so forth. Even the structure of our Markdowner
class is flawed when it comes to testing. To do pure unit testing on this class it should be structured such that instances of both the MarkdownExtra
and SmartyPants
classes are injected into the constructor. This way our unit test could inject mock objects and only verify the behavior of MarkdownExtra
and not the classes it calls.
But this isn’t a book on testing. In fact, this is the only chapter where testing is discussed. We’ll leave the structure as is but add just a couple more tests.
Update MarkdownerTest
to match what’s below.
<?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"],
];
}
}
Here we changed the test class to test multiple conversions at once and added three tests in conversionsProvider()
. Your tests should be green before moving forward.
Once the tests are green hit Ctrl+C
in your Host OS console to stop Gulp.
It’s not the intent here to provide a definitive list of all the ways to test with Laravel 5.1 because there’s really no single way to do testing in PHP. Therefore, there’s no single way to test in Laravel 5.
But, we’ll explore some alternatives.
Besides PHPUnit, Laravel 5.1 also provides phpspec out of the box. This is another popular PHP test suit with more of a focus on Behavior Driven Development.
Here’s a few notes on phpspec.
vendor/bin
, thus you can call phpspec
from your project’s root directory.phpspec.yml
.phpSpec()
function you can call on the mix
object.App
to something else, be sure to update phpspec.yml
accordingly.Although PHPUnit is the standard when it comes to PHP unit testing, there are other packages you can use.
These tests actually use your application instead of just verifying that units of code within your application work. When using the fluent test methods Laravel 5.1 provides you can actually do some functional tests using PHPUnit. ExampleTest.php
shows a simple example. But there are other testing frameworks that focus on functional / acceptance testing.
BDD comes in two flavors: SpecBDD and StoryBDD.
SpecDD focuses on the technical aspects of your code. Laravel 5.1 includes phpspec which is the standard for SpecDD.
StoryBDD emphasizes business or feature testing. Behat is the most popular StoryBDD framework. Although, Codeception can also be used for StoryBDD.
The first thing we did in this chapter was creating a project named l5beauty. Then we explored unit testing using PHPUnit within this project. Finally, we created a Markdowner
service class for the dual purposes of having something to test and to use later to convert markdown text to HTML.
This was a pretty long chapter because testing is a large topic and a single chapter cannot give it justice. But, as I’ve mentioned, testing is not the focus of this book. There will be no more testing in subsequent chapters.
How about something quicker for the next chapter?
标签:arch contents throw run http exist inject available sql
原文地址:http://www.cnblogs.com/kengdiexienima/p/6932958.html