1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

laravelでsitemap.xmlからHTTPテストを作る

Last updated at Posted at 2020-11-24

経緯

「とりあえずHTTPテストやりたいけど、構造はよく変わるしテストの維持がとても大変」
「関係ないけどsitemap.xmlの更新も面倒だなぁ」
「そうだ!sitemap.xmlからテストを作れば1度の修正で済むぞ!」

環境

laravel 6.19
PHPUnit 8.2.5

備考

前提として、テストを行うルート(sitemap.xmlに載せているルート)にnameが設定されている必要があります。

このテストは「sitemap.xml(このサイトに存在すると世界に示しているページ)にアクセス可能か」ということだけを検証するものです。
テストの管理が難しい環境で、最低限のHTTPテストとしてとりあえず入れてみるのには良いのでは無いかと思います。

出来たもの

sitemap/index.blade.php

<?php echo '<?xml version="1.0" encoding="UTF-8" ?>' . "\n"; ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <url>
        <loc>{{ route('home') }}</loc>
        <changefreq>daily</changefreq>
    </url>

    <url>
        <loc>{{ route('info') }}</loc>
        <changefreq>daily</changefreq>
    </url>

    {{--こういうshowページあったとする--}}
    @foreach($articles as $article)
        <url>
            <loc>{{ route('article.show', ['id' => $article->id]) }}</loc>
            <changefreq>daily</changefreq>
        </url>
    @endforeach

</urlset>
SiteMapTest.php
<?php

namespace Tests\Feature;

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

class SiteMapTest extends TestCase
{

    /**
     * 同一ルートを何個試すか
     */
    private $count = 3;

    /**
     * @test
     * @group sitemap
     * @dataProvider additionPrivateItems
     * @param string $url
     */
    public function test(string $url)
    {
        $response = $this->get($url);
        $response->assertStatus(200);
    }

    public function additionPrivateItems()
    {
        $xmlData = simplexml_load_string(view('sitemap.index')->render());
        $data = json_decode(json_encode($xmlData), TRUE)['url'];
        shuffle($data);

        foreach ($data as $url) {
            $url = $url['loc'];
            $routeName = $this->getRouteName(parse_url($url, PHP_URL_PATH) ?? '');

            if (empty($routes[$routeName]))
                $routes[$routeName] = 1;
            elseif ($routes[$routeName] >= $this->count)
                continue;
            else
                $routes[$routeName]++;

            yield [$url];
        }
    }

    private function getRouteName(string $uri)
    {
        return app('router')->getRoutes()->match(app('request')->create($uri))->getName();
    }
}

コードの中身

PHPunitのdataProviderを使ってテストケースを作っています。

laravelなら大体sitemap.xmlはblade使って生成していると思うので、

  • viewを->render()で文字列として取得
  • xml文字列をsimplexml_load_stringで取得
  • あれやこれやして配列で取得
  • 毎回ランダムなルートをテスト出来るようにシャッフルする
  • foreachで回し、それぞれURIからルート名を取得
  • 同じルートだったら個数制限する

という流れです。

PHPunitのgroupを設定しているので

./vendor/bin/phpunit --group=sitemap

これで実行出来ます。

終わり

これは本当に最低限の機能テストなので、フォームの送信テストなどPOST系のテストは別に用意出来ると良いです。
全部ルーティングから自動生成出来たらな。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?