Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 13.03.2018 16:38:19

В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом

Всем привет,
В Laravel 5.5/vue.js2.5  приложении делаю проверку CRUD операций  с помощью Dusk для таблицы document_categories:

    public function testExample()
    {
        $site_name = Settings::getValue('site_name', '');

//        try {
//            DB::beginTransaction();

            $document_category_id= '';
            $this->browse(function (Browser $browser) use ($site_name, $document_category_id) {
                $browser->resize(1920, 1080); // Width and Height
                $new_document_category = 'new document category created  at ' . time();
                $browser->loginAs(User::find(5))
                        ->visit('/admin/dashboard#/admin/document_categories/edit/new')
                        ->type('#name', $new_document_category)// Поле заполняется ->type , но НЕ заполняется если ->value
                        ->select('#type', 'D')// Enum field
                        ->type('#document_category_content', $new_document_category . ' content lorem...')// textarea input
                        ->click('.editor_button_submit')
                        ->waitUntilMissing('.editor_button_submit')
                        ->assertTitle('Document Categories of ' . $site_name)
//                        ->assertPathIs('/admin/dashboard#/admin/document_categories')
                ;
                $document_category_id= DB::getPdo()->lastInsertId();
                echo ' New document category id::'.print_r($document_category_id,true);
            });

            echo ' New document category id::'.print_r($document_category_id,true);

/*        } catch (Exception $e) {

            DB::rollBack();
            throw $e;
        }
        DB::commit();*/

    }

Новая строка вставляется, но:
1) Кроме добавления строки хочу по $document_category_id эту строку отредактировать и удалить для чего погуглив в коде выше
считываю

DB::getPdo()->lastInsertId(); 

но в консоль выводится 0. Тут нужно как-то иначе получить lastInsertId ?
Если раскоментарить блоки транзакции - то также получаю 0.

2) Это Vuejs 2.5 приложение с настройкой рутов:

const routes = [
    {
        path: '/',
        ...
        {path: '/admin/document_categories', component: DocumentCategoriesIndex, name: 'documentCategoriesIndex'},
        {path: '/admin/document_categories/edit/:id', component: DocumentCategoryEdit, name: 'editDocumentCategory'},
        ...
    ]

    const router = new VueRouter( {
        mode: 'hash', // default
        routes
      })

И при открытии формы для создания открывается урл :

http://local-tasks.com/admin/dashboard#/admin/document_categories/edit/new

И при сохранении переходит на

http://local-tasks.com/admin/dashboard#/admin/document_categories

И на последний assertPathIs получаю ошибку :

Tests\Browser\ExampleTest::testBasicExample
Failed asserting that '/admin/dashboard' matches PCRE pattern "/^\/admin\/dashboard#\/admin\/document_categories$/u".

Почему ошибка и как ее исправить ?

3) Кто в курсе реализации тестов Dusk-а подскажите а стоит ли заворачивать эти тесты в блоки транзакции как закоментировано выше ?

Спасибо !

Не в сети

#2 14.03.2018 00:27:40

Re: В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом

Дружище, привет. замечаний будет много

Первое - в тестах нужно использовать чистую отдельную БД и использовать трейт RefreshDatabase. это для того, чтобы А) - не засунуть/удалить по ошибке лишних данных в основную БД, Б) сделать жизнь проще. ларавел позволяет это сделать очень просто. в phpunit.xml, в тэге php добавь следующие записи

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

то есть будешь использовать sqlite базу подгружаемую в память. можно конечно и настроить отдельное MySql соединение в database.php для тестирования. но такой метод проще и в 95% случае именно то, что нужно

Второе, как уже сказал, заюзай трейт RefreshDatabase и убери все DB::beginTransaction rollback и коммит.

Третье - Теперь, когда у тебя чистая база, ты легко можешь сделать утверждения на счет того, что ты ожидаешь по результатам своего теста. Например, я так понимаю, что при сабмите формы кнопкой .editor_button_submit должна создаться новая запись в... DocumentCategory? ок, если так, наверно это у тебя модель? тогда ты можешь сделать следующее:

$this->assertEquals(1, DocumentCategory::count());

все - ты протестировал что у тебя создалась новая запись в DocumentCategory. Ты можешь быть в этом уверен, потому что ты начинал с чистой базы, и у тебя не было ни одной записи ни в DocumentCategory, ни в какой либо другой модели. Так же, ты можешь добавить утверждений

$documentCategory = DocumentCategory::first(); // взяли вновь созданную модель, тк она одна в базе
$this->assertEquals("D", $documentCategory->type); // проверяем, что то, что юзер ввел в форме, то и сохранилось в модель
$this->assertEquals("content lorem...", $documentCategory->content); // чтобы это проверить, избавься от time() - он не нужен тебе
$this->assertRedirect('uri');

ну и напоследок, dusk - не самый оптимальный выбор для тестирования поведения моделей. гораздо лучше тестировать на http уровне, что ларавел тоже делает очень простым и приятным занятием


$user = factory(User::class)->create();

$this->actingAs($user)->post('url куда уходить пост запрос',[
'type' => 'D',
'content' => 'Lorem ipsum...'
]);

Пишу бэкенд для своего мобильного приложения, делюсь с миром, заходите посмотреть, много всего интересного https://youtu.be/C5M6-ycJ5gs

Не в сети

#3 14.03.2018 14:43:19

Re: В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом

Спасибо за развернутый коментарий - очень полезно!
1)Но если юзать отдельную БД (не рабочую) и использовать трейт RefreshDatabase - не есть ли это излишне ?

2) Да и я бы предпочел 1 строку создать отредактировать и следом удалить(да и клиент так пишет) позтову вопрос почему не работает

DB::getPdo()->lastInsertId(); 

по-прежнему актуален

3) А чем  http теcтирование лучше? Ведь при таком тестировании  проверяются только контрол и модел?
А в случае Dusk-а и view. Или нет?

4) Клиент хочет сделать несколько файлов тестов чтобы их кроном запускать ночью(меньше нагрузка)
Можно ли получить результаты выполнения(кол-во успешных тестов и ошибок) и выслать их мейлом на админа?
Приходит мысль делать буферизацию и парсить оутпут, нет ли способа лучше?

Не в сети

#4 14.03.2018 21:08:42

Re: В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом

roll

кроном тесты на продакшене? но... зачем? нет, так не делают) зависимости для тестирования даже установлены в require-dev в композере - они по умолчанию на продакш не ставятся. Флоу: ты разрабатываешь фичу, используя тесты. когда твои тесты зеленые, ты можешь быть уверен, что твоя фича работает так как нужно. ты деплоишь код в продакшн. код в продакшене лежит протестированный и работает. и новый код туда не попадает, покуда твои тесты вновь зеленые - и так по кругу. так это работает. По вопросу конкретно, я не в курсе как можно получить отчет о результатах тестирования. Но блин! даже сама идея противоречивая))) то есть, с таким подходом получается, что ты допускаешь, что в продакшене будут фейлиться тесты! но так нельзя, код не может попасть в продакшн, если тесты фейлятся.

1 - нет, это не излишне, ни в коем случае. это делает твою жизнь проще, а в этом и суть тестов. когда у тебя в базе полно данных, ты не можешь наверняка составить ассерты

2) - но это три разных действия, должно обрабатываться трямя разными эндпоинтами, должны иметь три (как минимум своих теста)

3) тестирование на http уровне дает тебе намного более детальное представление о том что происходит, где что фейлится, где рушится логика, ты видишь как легко продвигаешься по стеку исключений от ошибки к ошибке. даск просто дает финальный фейл (как в твоем примере) и не понятно на каком этапе что сломалось. погляди мои видео https://www.youtube.com/watch?v=pUV_tVQlsBE - я сейчас пишу бэкенд для апи для своего приложения, делюсь тем что есть. круто что ты пытаешься внедрить тесты в свое воркфлоу, это правильный путь)
Вьюхи тоже можно нужно тестировать http уровне. допустим ты тестируешь листинг товаров. в фазе сетапа теста ты создаешь несколько товаров, (при этом создаешь их с такими параметрами, как нужно тебе, что опять же невозможно работая с нечистой базой). в фазе экшена делаешь гет запрос на эндпоинт. проверяешь что получил ответ такой то, урл у тебя такой то, проверяешь что вьюха получила необходимый набор из созданных тобою товаров. $this->assertViewHas. и все. а тестировать местоположение элементов на страницы - ну это такое. это значит что если ты решил изменить слегка дизайн, или например изменить формат даты во вьюхе, или используешь другой css фреймвор и классы твоих элементов поменялись - твои даск тесты упадут. будет ли это означать что твое приложение перестало работать? нет. ты просто поменял дизайн. для чего тогда тесты, если они не тестируют поведение, а ломаются от смены дизайна.
Бомбануло чот)) tongue

Изменено code_bright_anywhere (14.03.2018 21:10:07)


Пишу бэкенд для своего мобильного приложения, делюсь с миром, заходите посмотреть, много всего интересного https://youtu.be/C5M6-ycJ5gs

Не в сети

#5 15.03.2018 12:02:30

Re: В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом

Спасибо, еще раз!

1) А что это за метод assertEquals
Тут https://laravel.com/docs/5.5/dusk#available-assertions я такого не нашел ...
И чем его заменить - типа данное условие истинно ?

2) Пока с клиентом речь идет что будет одно приложение(поэтому тесты запускать ночью), но с двумя базами, поэтому я полагаю сделать в .env :

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=tasks
DB_DUSK_DATABASE=tasks_dusk
DB_USERNAME=root
DB_PASSWORD=1

И в config/database.php :

    'connections' => [

        'sqlite' => [
            'driver' => 'sqlite',
            'database' => env('DB_DATABASE', database_path('database.sqlite')),
            'prefix' => '',
        ],


        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => 'tsk_',
            'strict' => true,
            'engine' => null,
        ],
        'testing' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DUSK_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => 'tsk_',
            'strict' => true,
            'engine' => null,
        ],

И для тестирования будет взята база данных из 'testing' ?

3) И как сделать тестируемую базу ? Из рабочей очистить таблицы CRUD-ы к кторым будут тестироваться ? Еще есть нюансы?

Не в сети

#6 15.03.2018 12:16:57

Re: В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом

После того, как ты так настроил в database.php, в phpunit.xml пропиши <env name="DB_CONNECTION" value="testing"/> и тогда в тестах будет использоваться тестовая база. для сетапа ничего делать не нужно, твой трейт RefreshDatabase будет это делать сам - а именно, накатывать миграции перед каждым тестом.

AssertEquals это базовый ассерт предоставляемый phpunit, по ссылке что у тебя это конкретно даск ассерты, надстроенные уже над phpunit и расширяющие его возможности. ты легко можешь использовать все ассерты из phpunit в своих даск тесах, что очень круто. /vendor/phpunit/phpunit/src/Framework/Assert.php - здесь можно посмотреть все ассерты phpunit,  ну или в их документации

Данное условие истинно - есть ассерт $this->assertTrue($value). или $this->assertNotNull($value). соответственно есть и обратные, $this->assertFalse and $this->assertNull()


Пишу бэкенд для своего мобильного приложения, делюсь с миром, заходите посмотреть, много всего интересного https://youtu.be/C5M6-ycJ5gs

Не в сети

#7 15.03.2018 14:50:59

Re: В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом

А как прапвильно подключить, получаю ошибку

BadMethodCallException: Call to undefined method [assertEquals].

?
Я нашел

use PhpUnit\Framework; 
use Tests\TestCase;

но не помогает...

Не в сети

#8 15.03.2018 21:48:28

Re: В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом

твои даск тесты должны наследовать базовый DuskTestCase, который в свою очередь наследует PHPUnitTestCase. и все ассерты от туда доступны в твоем даск тесте. у тебя так? создавал тест командой artisan dusk:make?


Пишу бэкенд для своего мобильного приложения, делюсь с миром, заходите посмотреть, много всего интересного https://youtu.be/C5M6-ycJ5gs

Не в сети

#9 16.03.2018 09:23:02

Re: В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом

Пересоздал еще раз:

$ php artisan dusk:make documentCategoriesCRUD 
Test created successfully.

И получаю файл tests/Browser/documentCategoriesCRUD.php:

<?php

namespace Tests\Browser;

use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;

class documentCategoriesCRUD extends DuskTestCase
{
    /**
     * A Dusk test example.
     *
     * @return void
     */
    public function testExample()
    {
        $this->browse(function (Browser $browser) {
            $browser->visit('/')
                    ->assertSee('Laravel');
        });
    }
}

И в tests/DuskTestCase.php :

<?php

namespace Tests;

use Laravel\Dusk\TestCase as BaseTestCase;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;

abstract class DuskTestCase extends BaseTestCase
{
    use CreatesApplication;

    /**
     * Prepare for Dusk test execution.
     *
     * @beforeClass
     * @return void
     */
    public static function prepare()
    {
        static::startChromeDriver();
    }

    /**
     * Create the RemoteWebDriver instance.
     *
     * @return \Facebook\WebDriver\Remote\RemoteWebDriver
     */
    protected function driver()
    {
        $options = (new ChromeOptions)->addArguments([
            '--disable-gpu',
            '--headless'
        ]);

        return RemoteWebDriver::create(
            'http://localhost:9515', DesiredCapabilities::chrome()->setCapability(
                ChromeOptions::CAPABILITY, $options
            )
        );
    }
}

Если поменять вручную

abstract class DuskTestCase extends PHPUnitTestCase

То ошибка что  PHPUnitTestCase не найден и как его подключить ?


Имею :

$ php artisan --version 
Laravel Framework 5.5.35
 

В composer.json :

    "require-dev": {
        ...
        "phpunit/phpunit": "~6.0"
        ...
    },

?

Не в сети

#10 21.03.2018 15:04:03

Re: В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом

code_bright_anywhere, не мог бы выложить заголовки своих тестов с использованием методов assertEquals, assertStatus ?
По-прежнему ищу решение...

Не в сети

#11 31.03.2018 16:16:59

Re: В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом

привет, сори за длительный ответ

что фейлится при таком сетапе?

из документации все шаги выполнил? провайдер зарегистрировал?

в composer.json имеется

"autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },

Пишу бэкенд для своего мобильного приложения, делюсь с миром, заходите посмотреть, много всего интересного https://youtu.be/C5M6-ycJ5gs

Не в сети

Подвал раздела