Laravel测试后重置数据库

时间:2018-08-09 22:50:40

标签: sql laravel testing laravel-5 laravel-dusk

我刚刚开始使用Laravel Dusk测试我的项目,并且需要一些指导。运行所有可用的测试之后,我希望能够将数据库重置回运行测试之前的状态。 (如果在运行测试之前数据库中有任何条目,我仍然希望在运行测试后才能看到它们。但是,在测试过程中创建的任何完整内容,在测试运行完成后我都不想看到它们。 )关于如何实现此目标的任何指示?谢谢!

更新:

<?php

namespace Tests\Browser;

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

class UserRegisterTest extends DuskTestCase
{
    use DatabaseTransactions;
    /**
     * A test for user registration.
     * @group register
     * @return void
     */

    public function testRegisterUser()
    {
        //Register with all info filled out correctly
        $this->browse(function ($browser){
            $browser->visit('/register')
                    ->type('firstName', 'JenLogin')
                    ->type('lastName', 'Zhou')
                    ->type('email', 'testLogin@gmail.com')
                    ->type('bio', 'Hello, this user is for testing login purposes!')
                    ->type('location_zip', '11111')
                    ->type('password', '123456')
                    ->type('password_confirmation', '123456')
                    ->click('.btn-primary')
                    ->assertPathIs('/home')
                    ->click('.dropdown-toggle')
                    ->click('.dropdown-menu li:last-child');

        });

        $this->assertDatabaseHas('users', ['firstName' => 'JenLogin', 'lastName' => 'Zhou', 'email' => 'testLogin@gmail.com']);


    }

    /**
     * Register with duplicate user
     * @group register
     * @return void
     */
    public function testRegisterDuplicateUser(){

        $this->browse(function ($browser){
            $browser->visit('/register')
                ->type('firstName', 'JenLoginDup')
                ->type('lastName', 'Zhou')
                ->type('email', 'testLogin@gmail.com')
                ->type('bio', 'Hello, this user is for testing login purposes!')
                ->type('location_zip', '11111')
                ->type('password', '123456')
                ->type('password_confirmation', '123456')
                ->click('.btn-primary')
                ->assertPathIs('/register')
                ->assertSee('The email has already been taken.');
        });

        $this->assertDatabaseMissing('users', ['firstName' => 'JenLoginDup', 'lastName' => 'Zhou', 'email' => 'testLogin@gmail.com']);
    }

    /**
     * Register with incorrect password confirmation
     * @group register
     * @return void
     */
    public function testRegisterUserNoPassConfirm(){

        $this->browse(function ($browser){
            $browser->visit('/register')
                ->type('firstName', 'JenLoginPass')
                ->type('lastName', 'Zhou')
                ->type('email', 'testLoginPass@gmail.com')
                ->type('bio', 'Hello, this user is for testing login purposes!')
                ->type('location_zip', '11111')
                ->type('password', '123456')
                ->type('password_confirmation', '888888')
                ->click('.btn-primary')
                ->assertPathIs('/register')
                ->assertSee('The password confirmation does not match.');
        });

        $this->assertDatabaseMissing('users', ['firstName' => 'JenLoginPass', 'lastName' => 'Zhou', 'email' => 'testLoginPass@gmail.com']);
    }
}

7 个答案:

答案 0 :(得分:3)

您正在寻找DatabaseTransactions特性。像这样在测试类中使用它,它将自动回滚测试期间进行的所有数据库事务。     

use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseTransactions;

    // test methods here
}

这将跟踪测试期间进行的所有交易,并在完成后撤消它们。

注意:此特征仅适用于默认数据库连接

答案 1 :(得分:1)

没有健全的工作流程可在live / dev db上运行包含数据的测试,并还原由测试完成的更改。

因此,这里的方法失败了,相反,您应该:

  1. 为测试创建单独的测试架构/数据库
  2. 在运行测试之前切换到测试数据库-这可以自动进行,具体取决于您在phpunit和.env.dusk中的配置,但这取决于您的本地设置。
  3. 然后在您的测试中,您将从头开始在干净的数据库上创建所有文件(运行迁移,种子,工厂)
  4. 针对此测试数据库运行测试
  5. 要进行开发,请使用当前数据切换回基本数据库,该数据不受测试的影响。

下次您将运行测试时,所有操作将从零点重新开始-清理数据库,这将在测试中完成: use CreatesApplication; use DatabaseMigrations; parent::setUp();

详细了解这些方法...

注意事项:

  1. 使用这种方法,也很容易在CI环境中测试您的应用。

  2. 请不要编写依赖于dev / live数据库上数据的测试。为了进行测试,所有必需的数据应由种子或工厂提供!

答案 2 :(得分:1)

首先,在运行测试时,应该使用与实时数据库(或开发数据库)完全不同的数据库。为此,您应该创建.env.dusk并在其中设置:

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=testing_database
DB_USERNAME=root
DB_PASSWORD=pass

仅用于测试的数据库。

第二件事是,对于Laravel Dusk,您不能仅使用DatabaseTransactions。实际上,您应该使用DatabaseMigrations进行黄昏测试,否则会得到意想不到的结果。

答案 3 :(得分:0)

我认为这是一个很好的问题。我找到了可能正在寻找的Artisan工具。您可以在运行测试之前使用它来拍摄数据库快照,然后再次使用它来加载快照以将数据库恢复到先前的状态。我给它运行(使用MYSQL),效果很好。希望这是您想要的。这是链接...

https://github.com/spatie/laravel-db-snapshots

答案 4 :(得分:0)

phpunit.xml文件是您在那里的解决方案,您可以像这样在此文件中设置.env变量

    <env name="DB_CONNECTION" value="testing_mysql"/>
    <env name="DB_DATABASE_TEST" value="test"/>

现在您可以在单独的数据库上运行测试。

此外,您每次可以在自动化测试之前运行一个.php文件,您只需要将其告知单元测试

<phpunit 
     ...
     bootstrap="tests/autoload.php"
>

您可以在其中放置任何清洁剂或播种机或类似物

echo 'Migration -begin-' . "\n";
echo shell_exec('php artisan migrate:fresh --seed');
echo 'Migration -end-' . "\n";

答案 5 :(得分:0)

您可以在测试类中使用 RefreshDatabase trait。每次测试后,数据库将与测试前一样。 事实上,它将删除所有表并再次迁移。 如果您不想丢失数据,则可以使用一个单独的架构进行测试。

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

}

答案 6 :(得分:0)

对于多个数据库,这对我有帮助

class MyTest extends TestCase {
    // Reset the DB between tests
    use DatabaseTransactions;

    // Setting this allows both DB connections to be reset between tests
    protected $connectionsToTransact = ['mysql', 'myOtherConnection'];
}