2011年11月の Python 温泉でテストの実践方法を教えてもらう機会がありました。
初めて参加した Python 温泉で、 @voluntas と @aohta に開発プロセスの教えを乞いました。いろいろ教えてもらった中で、実際に手を動かし始めたことを書きます。
その後日談です。
単純だけど動く buildout.cfg を書けるようになったことが、今回のツール知識の中で最大の成果です。
温泉では buildout を使ってテストする側の環境をいっぱつで作れるようになりました。温泉から帰ってから、テストされる側、すなわち、製品側の環境用の buildout.cfg を書きました。
対象となるプロジェクトでは、Google App Enigne を使っていて、本番用と開発用にそれぞれ App Engine アプリを用意していたので、環境絡みの問題がすぐに分かりました。
大したコードではないので自社ライブラリにしなくていいんじゃ、と思ったのです。が、「call_api のテストだけ書いておけば、[simplejson などの] 依存先の使わない機能の不具合を無視できるのだから、自社ライブラリの動作確認だけすればよいでしょ。だから自社ライブラリにしちゃえ」という教えでした。これが一番私にとって重要な考え方でした。
いたく感動していた割に、まったく実践できていません。そして相変わらず車輪の再発明です。素振り、勉強としての車輪の再発明には意味があると思いますが、問題にしているのは避けるべき再発明なのですね。
ウェブAPIを作ることが多いので、製品側のコードも、テスト側のコードも共通化できることは確実にあるのです。なんでやっていないんですかね。なんか面倒そう、と思っているのでしょう。そして、その場で面倒をさけて、あとで面倒になるというわけです。
問題は、Twitter に問題があると、テストが FAILすることです。それは Twitter の問題であって、私が開発しているアプリケーションの問題ではありません。
なので、OAuth が成功した or 失敗したふりをしてくれるモックが必要です。それが次の課題だろうな、と考えています。
これも、ほったらかしです。具体的に何が必要かというと、OAuth Service Provider のインタフェースとモックだけ実装すればいいはずなんですけどね。今後の課題です(放置フラグ)。
何をしようとしているかというと、継続的インテグレーションをしたいのです。サーバサイドのエンジニアが少ないので、できるだけ自動化したいわけです。人間は創造的なことに時間を使うべきだ、と個人的に信じています(それでまあ、例の対談とかの流れになるわけです)。そのためには自動的に環境構築して、テストできるようにする必要があるのですが、ずーっと止まっていました。今回の温泉で、一歩目を踏み出せたのは大きな収穫でした。
デュバルらによる「継続的インテグレーション入門」では、「Integrate ボタンいっぱつで、ビルドできるようにせよ」というのが一貫した主張で、各要素の作りかた/考えかたが書かれています。
まず Jenkins を導入しました。リポジトリに変更があったら、ユニットテストの実行、GAE 開発アプリ空間へのデプロイ、機能テストの実行までをやりました。インスペクションとデータベースのインテグレーションも、ビルドに含むべきであると書かれていますが、そこまでは到達できていません。pep8 を手動では知らせてチェックインしていました。
データベースのインテグレーションが問題です。理屈の上では、古いバージョン用にデータセットが格納されていて、スキーマ(的なもの)が変更されるのであれば、その変更スクリプトを走らせて動かす、ってことになるのだと思います。あと、GAE の場合はインデックスの更新をリクエストする必要があります。
これはテストデータのセットを用意できていることが前提ですね。確かに、用意しないといけません。なんか作業が膨大そうに見えて、怖気づき、躊躇しています。
このプロジェクトは、継続的インテグレーションの実践の場になり、いくつかのことを学びました。まず何よりも、自動的にテストが走るのは非常に楽である、ということ。API呼び出しによる副作用が複雑で(これはこれで問題ではある)ちょっとした仕様変更でも、意外な影響範囲があったりしました。そういうときでも、テストがあるので安心して変更できました。ただし、テストの数がある程度たまるまでは、なかなかきつかったです。
一方で、継続的インテグレーションをぜんぶ実践するのは、大変そうに感じました。じつは大変ではないかかも知れません、一度走り出したら大変ではなくなるのかも知れませんし、実際に大変なのかも知れません。