自动化测试:六个值得参考的 Laravel 开源项目

file

最近我对自动化测试越来越感兴趣 —— 密切关注着 PHPUnit,TDD,Laravel Dusk,Travis 以及其他测试相关的关键词,所以我决定看看周围其他人是如何做自动化测试的。我在 GitHub 上找到了相当多的 Laravel 开源项目,从里面挑选出了 6 个来查看他们的测试方案。让我们分别看一下。

免责声明: 我只是查看了完整的基于 Laravel 5.3+ 的 Laravel 项目(不包括依赖包)

1. Laravel.io portal

URL: https://github.com/laravelio/portal

最近重新启动的 Laravel.io 已经将代码在 GitHub 上开源。Dries Vints 在这个项目中写的测试非常好。

file

Laravel.io 使用功能测试 (Feature testing) 和组件测试 (Component testing)(和单元测试差不多)。有趣的是,在这两种测试中都进行了相同或相似的测试。

例子 1 -- tests/Feature/ReplyTest.php

public function users_can_add_a_reply_to_a_thread()
{
    factory(Thread::class)->create(['subject' => 'The first thread', 'slug' => 'the-first-thread']);
    $this->login();
    $this->visit('/forum/the-first-thread')
        ->type('The first reply', 'body')
        ->press('Reply')
        ->see('The first thread')
        ->see('The first reply')
        ->see('Reply successfully added!');
}

例子 2 -- tests/Components/Jobs/CreateReplyTest.php

public function we_can_create_a_reply()
{
    $job = new CreateReply('Foo', '', $this->createUser(), factory(Thread::class)->create());
    $this->assertInstanceOf(Reply::class, $job->handle());
}

这样做很好: 同时测试 Jobs 层和实际在浏览器中点击一些东西。

我还注意到 Laravel.io 已经升级到了 Laravel 5.4, 但是测试套件仍然使用的是5.3的风格, 使用 BrowserKitTestCase implementation。 这没有什么问题,仅仅是一个提醒。

这个项目也使用了 Travis 进行持续集成, 后来我发现大多数项目都使用了它。

2. Cachet —— 一个开源状态页面系统

URL: https://github.com/cachethq/Cachet

James BrooksGraham Campbell 的带领下,这个项目有一个庞大的测试组件。他甚至通过观察表层很难理解。

file

所以,我们从哪里开始... 事实上,我甚至不会深度燕郊这个项目的测试逻辑, 因为他太难理解了,这是一个例子 —— tests/Models/ComponentTest.php

use AltThree\TestBench\ValidationTrait;
use CachetHQ\Cachet\Models\Component;
use CachetHQ\Tests\Cachet\AbstractTestCase;

class ComponentTest extends AbstractTestCase
{
    use ValidationTrait;
    public function testValidation()
    {
        $this->checkRules(new Component());
    }
}

好吧,这里用到了 ValidationTrait,然后是一些 AbstractTestCase。同时这段逻辑是所有的测试 —— 一些抽象的 "魔术" 正在执行所有的工作。

我不是说这是坏事 —— 十分确定他在内在的东西里工作的很好。他只是不容易先学习和遵循。但如果有人想深入研究 —— 祝好运!

3. October CMS

URL: https://github.com/octobercms/october

市场上第一款基于 Laravel 的 CMS,他拥有非常不错的测试组件。

file

首先 -—— tests 文件夹有一个 真正信息详实的 readme.md 文件,专门用于测试过程。

October CMS 的所有测试包括:

  • 单元测试
  • 功能测试
  • 插件测试

每个 "区域" 都有对应的基类来扩展 —— 有 TestCaseUiTestCasePluginTestCase

逻辑也非常复杂和抽象 —— 这里有一个例子 tests/unit/backend/models/ExportModelTest.php

class ExportModelTest extends TestCase
{
    //
    // 辅助
    //
    protected static function callProtectedMethod($object, $name, $params = [])
    {
        $className = get_class($object);
        $class = new ReflectionClass($className);
        $method = $class->getMethod($name);
        $method->setAccessible(true);
        return $method->invokeArgs($object, $params);
    }
    //
    // 测试
    //
    public function testEncodeArrayValue()
    {
        $model = new ExampleExportModel;
        $data = ['foo', 'bar'];
        $result = self::callProtectedMethod($model, 'encodeArrayValue', [$data]);
        $this->assertEquals('foo|bar', $result);
        $data = ['dps | heals | tank', 'paladin', 'berserker', 'gunner'];
        $result = self::callProtectedMethod($model, 'encodeArrayValue', [$data]);
        $this->assertEquals('dps \| heals \| tank|paladin|berserker|gunner', $result);
        $data = ['art direction', 'roman empire', 'sci-fi'];
        $result = self::callProtectedMethod($model, 'encodeArrayValue', [$data, '-']);
        $this->assertEquals('art direction-roman empire-sci\-fi', $result);
    }
}

如你所见,这里有一个静态辅助方法(顺便说一下,在其他类中重复使用),然后获取类/方法并调用他啊, 我确信作者能立即理解逻辑,但这对外人来说很困难。

同样有趣的是,OctoberCMS 使用 Selenium 来获取一些功能:tests/readme.md 文件提到了设置文档。

4. Orgmanager —— GitHub 组织的邀请系统

URL: https://github.com/orgmanager/orgmanager

这是 Miguel Piedrafita 的一个非常简单的项目,Orgmanager 的测试也是非常简单易懂的。还分为单元,功能和 API 测试。

file

我在这里看到一个有趣的示例 —— 从测试中调用 Artisan 命令,例如 unit/JoinTest.php

public function testJoinCommand()
{
    $user = factory(User::class)->create();
    $org = factory(Org::class)->create([
      'userid' => $user->id,
    ]);
    Github::shouldReceive('authenticate')
              ->once()
              ->with($org->user->token, null, 'http_token')
              ->andReturn();
    Artisan::call('orgmanager:joinorg', [
      'org'      => $org->id,
      'username' => $user->github_username,
    ]);
    $this->assertEquals($user->github_username.' was invited to '.$org->name."\n", Artisan::output());
}

调用 artisan 命令并断言其输出 —— 非常有趣。我确定他有效,但这是非标准的方式。

5. PHPMap

URL: https://github.com/PHPMap/phpmap

Florian Wartner 创建及维护。

file

PHPMap 有一个测试组件,使人联想到 Laracasts测试驱动 Laravel 课程 讲述的标准。这是 Feature/FavoritesTest.php 的例子。

public function guests_can_not_favorite_anything()
{
    $this->withExceptionHandling()
        ->post('forum/replies/1/favorites')
        ->assertRedirect('/login');
}

public function an_authenticated_user_can_favorite_any_reply()
{
    $this->signIn();
    $reply = create('App\Models\Forum\Reply');
    $this->post('forum/replies/'.$reply->id.'/forum/favorites');
    $this->assertCount(1, $reply->favorites);
}

PHPMap 的测试分为单元,功能及 Laravel Dusk 等等!最后我发现了一个真正在生产环境使用 Dusk 的项目。这是他的门面 —— tests/Browser/MapTest.php

public function testMap()
{
    $this->browse(function ($browser) {
        $browser->visit('/map')
                ->assertSee('PHPMap');
    });
}

6. Timegrid —— 免费,开源,在线操作平台

URL: https://github.com/timegridio/timegrid

Timegrid 的最大贡献者是 Ariel Vallese,同时他在测试方面做了非常好的工作。

file

这里只有很多的测试: 单元,验收和集成,每个文件都有更深的子文件夹目录,例如:—— acceptance/scenarios/consulting/ConsultingScenarioTest.php

public function it_fits_for_consulting_scenario()
{
    $this->arrangeScenario();
    $this->the_business_publishes_a_consulting_service();
    $this->the_business_publishes_vacancies();
    $this->a_user_subscribes_to_business();
    $this->the_user_queries_vacancies();
    $this->it_provides_available_times_for_requested_service_date();
    $this->the_user_takes_a_reservation();
    $this->the_user_sees_the_reservation_ticket();
}

public function the_business_publishes_a_consulting_service()
{
    $this->service = $this->makeService([
        'name'     => 'OnSite 4hs Support',
        'duration' => 60 * 4,
        ]);
    $this->actingAs($this->owner);
    $this->call('POST', route('manager.business.service.store', $this->business), $this->service->toArray());
    $this->assertCount(1, $this->business->fresh()->services);
}

一个一体化的方法,之后是一个个列举更多的测试:

仓库中的官方统计数据看起来非常好: 89% 的测试覆盖率

最后,有趣的是,作者甚至测试了迁移文件,如 tests/unit/migration/MigrationTest.php:

public function it_refreshes_rollbacks_and_seeds_the_database()
{
    $database = env('DB_CONNECTION');
    $this->assertNotNull($database);
    $exitCode = Artisan::call('migrate:refresh', ['--database' => $database]);
    $this->assertEquals(0, $exitCode);
    $exitCode = Artisan::call('migrate:rollback', ['--database' => $database]);
    $this->assertEquals(0, $exitCode);
    $exitCode = Artisan::call('migrate', ['--database' => $database]);
    $this->assertEquals(0, $exitCode);
    $exitCode = Artisan::call('db:seed', ['--database' => $database]);
    $this->assertEquals(0, $exitCode);
}

在测试中使用 Artisan 命令或许不是最佳的设计模式,但他只是测试任何 web 应用中最重要的功能之一。

总体结论

在看过所有这些不同的项目之后(以及由于各种原因未提及的),以下是我对自己关于测试的主要要求:

  • 不在 单元 "或" 功能 中做选择, —— 大多数项目两者兼具,或者更多类型的测试;
  • 大多数项目使用持续集成(通常是 Travis)和测试组件 —— 否则,为什么反感写测试呢?
  • 这里有非常多的不同方式构建测试 —— 这完全取决于项目,这里没有“高招”;
  • 还有很多方法对内部测试功能分组 —— 辅助方法,抽象类,种子数据等。没有具体规则,找准适用于你的内容。
  • 迁移到较新版本的 Laravel 可能很痛苦 —— 例如,5.3 版本的测试看上去和 5.4 版本不一样。所以你需要提前考虑更新。
  • 从不同角度考虑 —— 当你的项目成长起来,你将不得不回看及修改/添加测试。在这些项目中,我”预感“有一些遗留代码,只是因为有些测试将不在被使用。

以上是我的经验,有没有你要添加到开源项目列表中来学习测试的内容?

文章转自:https://learnku.com/laravel/t/24767

更多文章:https://learnku.com/laravel/c/translations

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • Laravel 学习交流 QQ 群:375462817 本文档前言Laravel 文档写的很好,只是新手看起来会有...
    Leonzai阅读 7,755评论 2 12
  • Laravel Dusk 控制台是一款 Laravel 扩展包,能够为你的 Dusk 测试套件提供漂亮的可视面板。...
    summerbluet阅读 1,008评论 0 0
  • ◆★◆酵素减肥产品排行榜,燕动力燕窝果冻,台湾酵素哪个品牌最好,什么牌子酵素减肥最好,酵素的作用和吃法◆★◆ --...
    a9fd91014b92阅读 2,876评论 0 0
  • 一个孩子,救了一个小精灵。小精灵答应他,可以满足他的三个愿望。 于是孩子大声说:“让所有欺骗过他人的人都变成石头吧...
    东门听风阅读 134评论 0 0
  • 生活,像一首诗 让我们领略生活的五彩缤纷 生活,像一首歌 让我们倾听这热血的歌喉 生活,像一朵云 让我们不畏艰难继...
    寒茗莞玥阅读 173评论 0 0