TDD

(Test Driven Development)

Ashley

Es un gestor de proyectos, con sus tareas y comentarios

Creación del proyecto Laravel

laravel new ashley
cd ashley

Probar en el navegador ashley.test

Git

//Crea un repositorio nuevo
git init

//Ver estado de archivo bajo seguimiento y modificados
git status

//Registrar cambios
git add .

git status

//Para hacer commit a los cambios
git commit -m 'Instalación del Framework'

//Obtener el commit id
git log

Comencemos con las pruebas (tests)

php artisan make:test ProjectTest

Se prueba en el proyecto y en la base de datos

vendor/bin/phpunit tests/feature/ProjectTest

Pruebas

use WithFaker, RefreshDatabase;
/** @test */
public function a_user_can_create_a_project()
{

    $attributes = [
        'title' => $this->faker->sentence,
        'description' => $this->faker->paragraph
    ];

    $this->post('/projects', $attributes);

    $this->assertDatabaseHas('projects', $attributes);

}

Creamos el código

vendor/bin/phpunit tests/feature/ProjectTest

Pruebas

DB_DATABASE=ashley
DB_USERNAME=root
DB_PASSWORD=

//Debemos crear la base de datos en MySQL

Configurar la base de datos en .env

vendor/bin/phpunit tests/feature/ProjectTest

Pruebas

<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>   

Configurar la base de datos en phpunit.xml

vendor/bin/phpunit tests/feature/ProjectTest

Pruebas

php artisan make:migration create_projects_table

Migraciones

php artisan make:model Project

Crear el modelo

//Quitar el control del excepciones para ProjectTest
$this->withoutExceptionHandling();

Control de Excepciones

Route::post('/projects', function(){
    //Validar
    //Almacenar
    App\Project::create(request(['title', 'description']));
    //Redireccionar
});

En web.php crear la ruta

//En el modelo Project
protected $guarded = [];
$table->string('title');
$table->text('description');

Agregar los campos en la migración create_projects_table

vendor/bin/phpunit tests/feature/ProjectTest

Pruebas

$table->string('title');
$table->text('description');

Agregar los campos en la migración create_projects_table

vendor/bin/phpunit tests/feature/ProjectTest

Pruebas

//En ProjectTest
$this->get('/projects')->assertSee($attributes['title']);

Ver el proyecto desde un get

Route::get('projects', function(){
    $projects = App\Project::all();
    return view ('projects.index', compact('projects'));
});

Crear el archivo: resources/views/projects/index.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <h1>Ashley</h1>
    <ul>
        @foreach ($projects as $project)
            <li>{{ $project->title }}</li>
        @endforeach
    </ul>
</body>
</html>

Refactoring

php artisan make:controller ProjectsController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Project;

class ProjectsController extends Controller
{
    public function index()
    {
        $projects = Project::all();

        return view('projects.index', compact('projects'));
    }

    public function store()
    {
        //Validar
        //Almacenar
        Project::create(request(['title', 'description']));
        //Redireccionar
    }
}

Test- redirección

$this->post('/projects', $attributes)->assertRedirect('/projects');
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Project;

class ProjectsController extends Controller
{
    public function index()
    {
        $projects = Project::all();

        return view('projects.index', compact('projects'));
    }

    public function store()
    {
        //Validar
        //Almacenar
        Project::create(request(['title', 'description']));
        //Redireccionar
        return redirect('/projects');
    }
}

Validación del Título

/** @test */
public function a_project_require_a_title()
{
  $this->post('/projects', [])->assertSessionHasErrors('title');
}
vendor/bin/phpunit --filter a_project_require_a_title

//Creamos un alias alias con: alias pf="vendor/bin/phpunit --filter"

pf a_project_require_a_title

Validación del Request en Store

    public function store()
    {
        //Validar
        request()->validate(['title'=>'required']);
        //Almacenar
        Project::create(request(['title', 'description']));
        //Redireccionar
        return redirect('/projects');
    }

Validación de la decripción

    /** @test */
    public function a_project_require_a_description()
    {
        $this->post('/projects', [])->assertSessionHasErrors('description');
    }  
    public function store()
    {
        //Validar
        request()->validate(['title'=>'required', 'description' => 'required']);
        //Almacenar
        Project::create(request(['title', 'description']));
        //Redireccionar
        return redirect('/projects');
    }

Factory

php artisan make:factory ProjectFactory --model="App\Project"

Son una muy buena forma para crear datos de prueba en la aplicación, esta clase recibe una instancia de la clase Faker que permite generar una gran variedad de valores de forma aleatoria.

use App\Project;
use Faker\Generator as Faker;

$factory->define(Project::class, function (Faker $faker) {
    return [
        'title' => $faker->sentence,
        'description' => $faker->paragraph
    ];
});
/** Tinker es una consola de comandos integrada en Laravel que
permite ejecutar y probar todas las funciones y módulos de tu aplicación */

php artisan tinker
factory('App\Project')->make();

Usar Factory

    public function a_project_require_a_title()
    {
        $atributes = factory('App\Project')->raw(['title' => '']);
        $this->post('/projects', $atributes)->assertSessionHasErrors('title');
    }

    /** @test */
    public function a_project_require_a_description()
    {
        $atributes = factory('App\Project')->raw(['description'=>'']);
        $this->post('/projects', [])->assertSessionHasErrors('description');
    }    

Refactoring

    public function store()
    {
        //Validar
        $atributes = request()->validate(['title'=>'required', 'description' => 'required']);
        //Almacenar
        Project::create($atributes);
        //Redireccionar
        return redirect('/projects');
    }

Modelo Project

    /** @test */
    public function a_user_can_view_a_project()
    {
        $this->withoutExceptionHandling();
        $project = factory('App\Project')->make();
        $this->get('/projects/'.$project->id)
            ->assertSee($project->title)
            ->assertSee($project->description);
    }
Route::get('/projects', 'ProjectsController@show');
    public function show()
    {
        $project = Project::findOrFail(request('project'));

        return view ('projects.show', compact('project'));
    }

Vista Project

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <h1>{{$project->title}}</h1>
    <p>{{$project->description}}</p>
</body>
</html>

Refactoring: Model Inject

    public function show(Project $project)
    {
        return view ('projects.show', compact('project'));
    }
Made with Slides.com