ほーむぺーじ制作な現場の話。
ここ数年でフレームワークやテンプレートエンジンの乗り換えとかアップグレードとかを何度となく繰り返してます。サイトの機能拡充をしようと思ったらシステムが古いので、一旦、最新のシステムに乗せ換えてから作業に取りかかりたい。でもレガシーウェブ制作なので、テストケースなんてないし、全部目視で確認するのは辛い。
新システムで旧システムと同じ動作を再現できたことを確認するためにCompBotというのを使ってます。Mojolicious + Text::Diffで2つのサイトのリンクを辿りながら差分を検出するモジュールです。
https://github.com/jamadam/CompBot
テスト全体は下記のような感じになります。diff.tとでもして保存します。
use strict; use warnings; use utf8; use CompBot; my $cbot = CompBot->new; $cbot->url_match(qr{dev.example.com}); $cbot->url_translate(sub { my $url = shift; $url->host('example.com'); return $url; }); $cbot->start('http://dev.example.com/');
実行。
$ perl diff.t
CompBotは、対応する2つのページのレスポンスボディをText::Diffにかけて、その結果をTest::Moreに投げてるので下記のような出力が得られます。
ok 666 - exact match for http://dev.example.com/menu/list_s.html?sh=1301&ty=7 ok 667 - exact match for http://dev.example.com/menu/detail_s.html?sh=1873&ty=11&id=131 ok 668 - exact match for http://dev.example.com/shop/bm_shop.html?cond1=1992 ok 669 - exact match for http://dev.example.com/menu/detail_s.html?sh=110&ty=11&id=125 ok 670 - exact match for http://dev.example.com/menu/list_s.html?sh=1873&ty=7 ok 671 - exact match for http://dev.example.com/menu/list_s.html?sh=1873&ty=8 not ok 672 - exact match for http://dev.example.com/menu/list_m.html?ty=1 # Failed test 'exact match for http://dev.example.com/menu/list_m.html?ty=1' # at /lib/CompBot.pm line 69. # got: '@@ -360,8 +360,7 @@ # <span class="weight">100g</span> # </div> # </td> # -</tr> # </table> # <div id="sidemenu"> # <!-- a --> # <!-- b --> # # ' # expected: '' ok 673 - exact match for http://dev.example.com/menu/detail_s.html?sh=1733&ty=6&id=88 ok 674 - exact match for http://dev.example.com/menu/detail_s.html?sh=1655&ty=0&id=23 ok 675 - exact match for http://dev.example.com/menu/detail_s.html?sh=203&ty=2&id=251 ok 676 - exact match for http://dev.example.com/menu/detail_s.html?sh=1053&ty=11&id=129
サイトAとサイトBを比較する場合、サイトAから検出したURLをurl_translateで加工してサイトB用のURLを作ります。Mojo::URLインスタンスが渡ってくるので、ホスト名をスイッチするなりパスを書き換えるなり、ポート番号を変えるなりしてreturnします。
$cbot->url_translate(sub { my $url = shift; # Mojo::URLインスタンス $url->host('example.com'); return $url; });
レスポンスボディは比較前に改変できます。新/旧のテンプレートエンジンでインデントスタイルとかが一致しないと散々な結果になるので、正規表現で無理やり一致させたりします。あと、Mojo::DOMを通すとHTMLタグが正規化されて、どうでもいい差分が吸収されるっぽいです。この辺テキトー。
$cbot->preprocess_a(\&preprocess); $cbot->preprocess_b(\&preprocess); use Mojo::DOM; sub preprocess { my $body = shift; $body =~ s{[ \t]+$}{}gm; $body =~ s{^[ \t]+}{}gms; $body =~ s{\n+}{\n}gms; $body = Mojo::DOM->new($body)->to_xml; return $body; }
text/*なレスポンスは全部Text::Diffの対象になります。画像は単純にレスポンスボディを比較します。画像やCSSなどはあまり動的に書き出さないので、拡張子で対象から外すこともできます。あと、URLでフィルタもできます。
$cbot->extension_not([qw{jpg png gif css js}]); $cbot->url_match(qr{dev.example.com/}); $cbot->url_not_match(qr{dev.example.com/test1/}); $cbot->url_not_match(qr{dev.example.com/test2/});
パラメータ含めると何万ページにもなったりして、全部チェックする気はありません。サンプリング検査的に実行したいのでキューをシャッフルします。
$cbot->shuffle(1);
これで、OKが1000件くらい並べば、正しく乗せ換えできたっぽいなあ、と少し安心できます。テキトーです。