国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

寫Laravel測試代碼(一)

MageekChiu / 2778人閱讀

摘要:在中可以在設(shè)置數(shù)據(jù)庫重裝操作這樣就可以在每一個中定義本次污染的數(shù)據(jù)表,保證下一個在運行前重刷下被污染的數(shù)據(jù)表,如這樣會極大提高數(shù)據(jù)庫測試效率,不推薦使用給出的和,效率并不高。

本文主要探討寫數(shù)據(jù)庫測試。

寫laravel程序時,除了寫生產(chǎn)代碼,還需要寫測試代碼。其中,寫數(shù)據(jù)庫測試比較麻煩,因為需要針對每一個test case需要建立好數(shù)據(jù)集,該次test case污染的數(shù)據(jù)表還需要恢復(fù)現(xiàn)場,避免影響下一個test case運行,同時還得保證性能問題,否則隨著程序不斷膨脹,測試數(shù)量也越多,那每一次測試運行需要花費大量時間。

有兩個比較好的方法可以提高數(shù)據(jù)庫測試性能:

對大量的tests按照功能分組。如有1000個tests,可以按照業(yè)務(wù)功能分組,如group1:1-200, group2:201-800, group3: 801-1000。這樣可以并發(fā)運行每組測試包裹。

只恢復(fù)每個test case污染的表,而不需要把所有的數(shù)據(jù)表重新恢復(fù),否則表數(shù)量越多測試代碼執(zhí)行越慢。

這里聊下方法2的具體做法。

假設(shè)程序有50張表,每次運行測試時首先需要為每組構(gòu)建好獨立的對應(yīng)數(shù)據(jù)庫,然后創(chuàng)建數(shù)據(jù)表,最后就是填充測試數(shù)據(jù)(fixtures)。fixtures可用yml格式定義,既直觀也方便維護(hù),如:

#simple.yml
accounts:
  - id: 1
    person_id: 2
    type: investment
    is_included: true
  - id: 2
    person_id: 2
    type: investment
    is_included: true
transactions:
  - account_id: 1
    posted_date: "2017-01-01"
    amount: 10000
    transaction_category_id: 1   
  - account_id: 2
    posted_date: "2017-01-02"
    amount: 10001
    transaction_category_id: 2

然后需要寫個yamlSeeder class來把數(shù)據(jù)集填充到臨時數(shù)據(jù)庫里:

abstract class YamlSeeder extends IlluminateDatabaseSeeder
{
    private $files;

    public function __construct(array $files)
    {
        $this->files = $files
    }
    
    public function run(array $tables = []): void
    {
        // Close unique and foreign key constraint
        $db = $this->container["db"];
        $db->statement("SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;");
        $db->statement("SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;");
        
        foreach($this->files as $file) {
            ...
            
            // Convert yaml data to array
            $fixtures = SymfonyComponentYamlYaml::parse(file_get_contents($file));
            
            ...
            
            foreach($fixtures as $table => $data) {
                // Only seed specified tables, it is important!!!
                if ($tables && !in_array($table, $tables, true)) {
                    continue;
                }
                
                $db->table($table)->truncate();

                if (!$db->table($table)->insert($data)) {
                    throw new RuntimeException("xxx");
                }
            }
            
            ...
        }
        
        // Open unique and foreign key constraint
        $db->statement("SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;");
        $db->statement("SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;");
    }
}

class SimpleYamlSeeder extends YamlSeeder
{
    public function __construct()
    {
        parent::__construct([database.path("seeds/simple.yml")]);
    }
}

上面的代碼有一個關(guān)鍵處是參數(shù)$tables:如果參數(shù)是空數(shù)組,就把所有數(shù)據(jù)表數(shù)據(jù)插入隨機(jī)數(shù)據(jù)庫里;如果是指定的數(shù)據(jù)表,只重刷指定的數(shù)據(jù)表。這樣會很大提高數(shù)據(jù)庫測試的性能,因為可以在每一個test case里只需要指定本次測試所污染的數(shù)據(jù)表。在tests/TestCase.php中可以在setUp()設(shè)置數(shù)據(jù)庫重裝操作:

    abstract class TestCase extends IlluminateFoundationTestingTestCase
    {
        protected static $tablesToReseed = [];
        
        public function seed($class = "DatabaseSeeder", array $tables = []): void
        {
            $this->artisan("db:seed", ["--class" => $class, "--tables" => implode(",", $tables)]);
        }
        
        protected function reseed(): void
        {
            // TEST_SEEDERS is defined in phpunit.xml, e.g. 
            $seeders = env("TEST_SEEDERS") ? explode(",", env("TEST_SEEDERS")) : [];
            
            if ($seeders && is_array(static::$tablesToReseed)) {
                foreach ($seeders as $seeder) {
                    $this->seed($seeder, static::$tablesToReseed);
                }
            }
            
            Cache::flush();
            
            static::$tablesToReseed = false;
        }
        
        protected static function reseedInNextTest(array $tables = []): void
        {
            static::$tablesToReseed = $tables;
        }
    }

這樣就可以在每一個test case中定義本次污染的數(shù)據(jù)表,保證下一個test case在運行前重刷下被污染的數(shù)據(jù)表,如:

    final class AccountControllerTest extends TestCase
    {
        ...
        
        public function testUpdateAccount()
        {
            static::reseedInNextTest([Account::class, Transaction::class]);
            
            ...
        }
        
    }

這樣會極大提高數(shù)據(jù)庫測試效率,不推薦使用Laravel給出的IlluminateFoundationTestingDatabaseMigrations 和 IlluminateFoundationTestingDatabaseTransactions,效率并不高。

laravel的db:seed命令沒有--tables這個options,所以需要擴(kuò)展IlluminateDatabaseConsoleSeedsSeedCommand:

class SeedCommand extends IlluminateDatabaseConsoleSeedsSeedCommand
{
    public function fire()
    {
        if (!$this->confirmToProceed()) {
            return;
        }

        $this->resolver->setDefaultConnection($this->getDatabase());

        Model::unguarded(function () {
            $this->getSeeder()->run($this->getTables());
        });
    }
    
    protected function getTables()
    {
        $tables = $this->input->getOption("tables");

        return $tables ? explode(",", $tables) : [];
    }

    protected function getOptions()
    {
        $options   = parent::getOptions();
        $options[] = ["tables", null, InputOption::VALUE_OPTIONAL, "A comma-separated list of tables to seed, all if left empty"];

        return $options;
    }
}

當(dāng)然還得寫SeedServiceProvider()來覆蓋原有的IlluminateFoundationProvidersConsoleSupportServiceProvider::registerSeedCommand()中注冊的command.seed,然后在config/app.php中注冊:

class SeedServiceProvider extends ServiceProvider
{
    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = true;

    /**
     * @see IlluminateDatabaseSeedServiceProvider::registerSeedCommand()
     */
    public function register()
    {
        $this->app->singleton("command.seed", function ($app) {
            return new SeedCommand($app["db"]);
        });

        $this->commands("command.seed");
    }

    public function provides()
    {
        return ["command.seed"];
    }
}

OK,這樣所有的工作都做完了。。以后寫數(shù)據(jù)庫測試性能會提高很多,大量的test case可以在短時間內(nèi)運行完畢。

最后,寫測試代碼是必須的,好處非常多,隨著項目程序越來越大,就會深深感覺到寫測試是必須的,一勞永逸,值得花時間投資。也是作為一名軟件工程師的必備要求。

RightCapital招聘Laravel DevOps

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/23105.html

相關(guān)文章

  • Laravel測試代碼(二)

    摘要:本文主要探討數(shù)據(jù)庫測試。在寫測試代碼一中聊了關(guān)于如何提高數(shù)據(jù)庫測試性能,其實簡單一句就是每一個只重新被污染的表。最后還得在中創(chuàng)建用戶并授權(quán),以用戶登錄這樣就臨時測試數(shù)據(jù)庫就準(zhǔn)備完畢了,然后就是測試數(shù)據(jù),執(zhí)行,執(zhí)行等等,可以參考寫測試代碼一。 本文主要探討數(shù)據(jù)庫測試。 在寫Laravel測試代碼(一) 中聊了關(guān)于如何提高 laravel 數(shù)據(jù)庫測試性能,其實簡單一句就是:每一個test ...

    Jackwoo 評論0 收藏0
  • Laravel 測試代碼(五)

    摘要:寫一個,的是,的內(nèi)容參照寫測試代碼三,然后寫上很明顯,這里測試的是,即和,是一個自定義的,主要功能就是實現(xiàn)了全部,并保存在文件里作為。 本文主要探討寫laravel integration/functional test cases時候,如何assert。前面幾篇文章主要聊了如何reseed測試數(shù)據(jù),mock數(shù)據(jù),本篇主要聊下assert的可行實踐,盡管laravel官方文檔聊了Tes...

    xbynet 評論0 收藏0
  • Laravel 菜鳥晉級之路

    摘要:用也有三四個月了,雖然是兼職開發(fā),但是使用的頻率非常之高,畢竟是產(chǎn)品化的一個項目。第二階段數(shù)據(jù)庫和開發(fā)了比較多的功能之后,會發(fā)現(xiàn)需要大量的測試數(shù)據(jù),這時候和就該大顯身手了。 用Laravel也有三四個月了,雖然是兼職開發(fā),但是使用的頻率非常之高,畢竟是產(chǎn)品化的一個項目。在這期間,也踩了無數(shù)的坑,走了很多彎路,所以準(zhǔn)備把最近的感悟記錄下來,方便后來者。 第一階段:簡單的增刪改查 這是最...

    YacaToy 評論0 收藏0
  • Laravel 中設(shè)計模式的實戰(zhàn)分享

    摘要:如何在實戰(zhàn)中能應(yīng)用上設(shè)計模式,我思考了接近兩年。最開始我接觸設(shè)計模式,出發(fā)點就是為了重構(gòu)代碼,以便更好的復(fù)用和測試。也就是說基本是被當(dāng)成一組靜態(tài)函數(shù)使用的。 MVC是Laravel自帶的,大家也多少都會用一些。今天我們不談MVC,談一些大中型項目的設(shè)計思路。 前言 雖然標(biāo)題說是設(shè)計模式,但是我并不打算去講什么singleton、strategy、factory,不知道為什么,每次看到...

    李義 評論0 收藏0
  • Laravel 中的數(shù)據(jù)遷移和數(shù)據(jù)填充

    摘要:本文首發(fā)于作者這是一篇基礎(chǔ)教程,對標(biāo)文檔中的數(shù)據(jù)遷移和數(shù)據(jù)填充。那么,中的數(shù)據(jù)庫遷移概念,就是用于解決團(tuán)隊中保證數(shù)據(jù)庫結(jié)構(gòu)一致的方案。和不同,如果多次執(zhí)行就會進(jìn)行多次數(shù)據(jù)填充。好了,數(shù)據(jù)遷移和數(shù)據(jù)填充的基本操作也就這些了。 showImg(https://segmentfault.com/img/remote/1460000012252769?w=648&h=422); 本文首發(fā)于 h...

    mengera88 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<