2012年3月5日月曜日

webtestで日本語を使うときの注意点

GAE の ローカルのユニットテストにwebtestというパッケージを利用しているのですが、日本語関連でちょっとはまってしまったので、書きます。


from webtest import TestApp
app = TestApp(testtarget_app)
app.get('/')
app.post('/search', {'title': u'sample検索文字列'}

ってやると、エラーは起きないのですが、文字化けします。
非ASCII文字は?に変換されちゃうんですよね。


調べてみたところ、get時のURLエンコードの前処理で
ユニコード文字列をバイト文字列にエンコードする際に、
符号化する文字コードを特定できないことが根本原因のようです。

つまり、
「どの文字コードで表現するべきか良くわからないんで、とりあえず?にしてみました!」
という処理ですね!(げげげ)


回避方法その1:post時はユニコード文字列を渡さない。
from webtest import TestApp
app = TestApp(testtarget_app)
app.get('/')
app.post('/search', {'title': u'検索文字列'.encode('utf-8')}

PythonでWebアプリを作る場合、どこまでを内部としてUNICODEで処理し、どこからを外部としてエンコードするかは大事ですね。
ユニコード文字列を受け取ってくれるから、良いように処理してくれると思ったらそうじゃないところが落とし穴でした。
(こんなわかりにくい処理を埋め込むくらいなら、エンコード時にエラーにしてくれた方が親切だと思います!)


でも、エンコードするのは格好悪いなぁと思い、webtestのソースを追っていたら、もっと便利そうな方法を見つけました。

回避方法その2:

from webtest import TestApp
app = TestApp(testtarget_app)
resp = app.get('/')
resp.form.submit('/search', {'title': u'sample検索文字列')


要はgetは比較的低レベルなAPIみたいですね。
getやpostした後に帰ってくるTestResponseクラスには、もう少し高レベルなAPIが用意されています。
そちらを使うと、都合の良い文字コードへのエンコードや、
通常ブラウザがやってくれるurlエンコードとかも自動でやってくれるみたいです。

同様にgetも本当はあんまり使わないほうがよくて、TestResponseのclickとかclickbuttonを使うほうが良いみたいですね。


私が未熟なので文字コード関連ではまることがありますが、全体的にWebtestの出来は結構良いですね。
テスト始める前は必要だと思っていたBeautifulSoupは、あんまりいらない感じです。

0 件のコメント:

コメントを投稿