【问题标题】:Laravel Reset Database after TestLaravel 测试后重置数据库
【发布时间】:2023-03-28 12:02:01
【问题描述】:

我刚刚开始使用 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']);
    }
}

【问题讨论】:

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


    【解决方案1】:

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

    use Illuminate\Foundation\Testing\DatabaseTransactions;
    
    class ExampleTest extends TestCase
    {
        use DatabaseTransactions;
    
        // test methods here
    }
    

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

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

    【讨论】:

    • 我添加了 "use DatabaseTransactions" 行,但收到​​此错误 "Fatal error: Trait 'Tests\Browser\DatabaseTransactions' not found in /Users/jenniferzhou/Documents/Cypress/MarketPlace/tests/Browser /UserRegisterTest.php 第 17 行"。
    • 您是否也包括了顶级使用声明use Illuminate\Foundation\Testing\DatabaseTransactions;?这应该高于类声明。然后use DatabaseTransactions; 语句应该就在上面演示的开头类行内。
    • 我添加了该行,现在我不再收到错误。但是,当我创建一个测试以在我的数据库中注册用户并添加行以使用 DatabaseTransactions 时,数据库仍然会在测试结束时存储用户。
    • 你能发布你的测试课吗?是否有异常被抛出、其他一些提前退出或正在运行完成?
    • 我添加了一个我尝试与数据库事务一起使用的测试!
    【解决方案2】:

    首先,当您运行测试时,您应该使用与实时(或开发)数据库完全不同的数据库。为此,您应该创建 .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 进行 Dusk 测试,否则你会得到意想不到的结果。

    【讨论】:

      【解决方案3】:

      没有健全的工作流程可以在 live/dev db 上使用数据运行测试并恢复更改,由测试完成。

      因此你的方法在这里失败了,你应该:

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

      下次您将运行您的测试时,一切都会从零点重新开始 - 清理数据库,这将在测试中完成: use CreatesApplication; use DatabaseMigrations; parent::setUp();etc.

      阅读有关这些方法的更多信息...

      旁注:

      1. 使用这种方法,可以很容易地在 CI 环境中测试您的应用程序。

      2. 永远不要编写依赖于开发/实时数据库上数据的测试。对于测试,所有必需的数据都应由种子或最终工厂提供!

      【讨论】:

        【解决方案4】:

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

        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'];
        }
        

        【讨论】:

          【解决方案5】:

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

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

          【讨论】:

          • 是的,这是一个很棒的包,但我不认为它是这种用法的主要目的,在工作中取消测试怎么样?它是否涵盖了所有请求的场景?当然不是。还有一些您需要调用的工匠命令。那么,修改.env 以匹配正确的测试数据库而不是切换回来不是更容易吗?
          【解决方案6】:

          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";
          

          【讨论】:

            【解决方案7】:

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

            use Illuminate\Foundation\Testing\RefreshDatabase;
            use Illuminate\Foundation\Testing\WithoutMiddleware;
            use Tests\TestCase;
            
            class ExampleTest extends TestCase
            {
                use RefreshDatabase;
            
            }
            

            【讨论】:

              猜你喜欢
              • 2019-08-29
              • 2014-09-03
              • 2014-12-19
              • 2013-11-08
              • 2019-01-01
              • 2018-05-23
              • 1970-01-01
              • 2019-10-29
              • 1970-01-01
              相关资源
              最近更新 更多