Pythonでテストしたい

Dec 18, 2017

これは、PyLadies Advent Calendar 2017の 18日目です。

はじめに

エモい話は諦めて、これからテストを掘り下げていこうと思っているのでそちらについて書きます。

最近、本を読んだりインターネットで調べているときにスケッチブックに書いていくのにハマっています。 あとで見返したりできるし、まとめるために要約を考えたりするので結構良いなと思っています。

テストについて

Python ライブラリ厳選レシピ 第11章テストとデバック

Python ライブラリ厳選レシピ の11章の内容を参考に各モジュールについて確認していきます。

pydoc

pydocモジュールは、Pythonモジュールから自動的にドキュメントを生成します。 help() と同じ機能をコマンドラインから利用できる他に、-w オプションを付けるとhtmlを出力してくれるそうです。 また、確認用の簡易HTTPサーバーをローカルに起動できるそうです。便利ですね。

実施例はこちら: pydoc

doctest

Pythonファイル中のコメント内の対話的実行例形式で書かれているものが実行されてテストができます。別ファイルに書くこともできるようです。

実施例はこちら: doctestを触ってみた

unittest

他の言語にもあって馴染み深いのがUnitテストですね。

実施例はこちら: unittestの公式ドキュメントを読んでみた

unittest.mock

テストがオブジェクトに依存する場合にその疑似オブジェクトを用意するためのものですね。

実施例はこちら: まだです。

pdb

デバック用のモジュールですね。今度、PyCharmのでバックと合わせて書きたいです。

実施例はこちら: まだです。

timeit

コードの実行時間を計測するモジュール

実施例はこちら: まだです。

pytest

サードパーティー製の高度なユニットテストモジュールです。普段はあまり使わないのですが、本も出たし、攻略していきたいです。

実施例はこちら: まだです。

traceback

スタックトレース用のモジュールみたいですね。

実施例はこちら: まだです。

logging

ログ用のモジュールみたいですね。

実施例はこちら: まだです。

後半のモジュールは手がつけれていないですが、おいおいやっていきます。

今日の参考書籍:

今回、参考にした参考書です。

この本は最近買ったので、ざっとしか読んでないですが1章ずつ噛み締めていきます。

普通の初心者向け本はテストについて書いてあっても触りだけですが、 この本はテストについてきちんと記述があります。 初めて手にするにはPythonの単体テストについてよくまとまっていて読みやすいと思います。

一度読んでおくと良さそうです。こちらもガッツリとは読んでいないので今後読んでいきたいです。

PyCon JP 2016にブースを出した話

Dec 13, 2017

これは、PyLadies Advent Calendar 2017の 13日目です。

エモい話!とか盛り上がってたんですが、全然思いつきませんでした。 そんなわけで、PyCon JPにブースを出したときの思い出を語ります。 いままで2016、2017と2回出展しています。 初回だった2016のほうが思い出深いので去年の話で申し訳ないですが、こっちを書きます。ちなみに今年もほとんど同じでした。 これからはじめてブースを出そうという方の参考になると嬉しいです。

決意

はじめて自社サービスを開発するメンバーになりました。 しかし、私の会社には「広報担当」的な人がいません。というかエンジニア以外の人がほぼいません。 売上も立っていない状態で新規に雇えるわけもなく、広報的なことは自分たちでやることになりました。

どうしたらいいのかわからなかったのですが、まぁ、宣伝しよう!ということで最初のやったのはPyCon JPへのブース出展でした。

申し込み&出展確定

そんなこんなでPyCon JP 2016にブースを出す計画をはじめました。 はじめはあまり明確な理由はなく「楽しそう」くらいで出そう思いました。 しかし、それでは会社的にNGということで、「β版をお披露目して、β版ユーザーを募る」という目的で出展することにしました。

以前の所属会社でも何度かブースに立ったことはあったんですが、どの会社にもマーケティング担当者がいたのでブースに展示する商品の説明をするだけでそれ以外のことはしたことがなかったです。

今回は全体の責任者ということで、まず「ブースを出すための手配」からはじめました。

PyCon JPにブースを出すにはスポンサーになる必要があります。会社が毎年シルバースポンサーをやっていたのでこれはクリアです。 しかし、シルバースポンサーなだけだとブースの権利が抽選になります。ゴールドのスポンサーの出展希望が多いと抽選も無くなるそうです。 シルバースポンサーかつ、ブースを出したい場合は「早期確定オプション」を追加で申し込む必要があります。私たちも申し込んで出展を確定させました。

遅くとも5月くらいにはスポンサー申し込みをしたほうが良さそうです。 ゴールドスポンサー以上ならスポンサーにさえなれれば、ブースとジョブフェアに条件無しで出せるみたいです。(たぶん) しかし、近年は上位スポンサーが埋まるの早いようです。 シルバースポンサーは早期確定オプションと合わせて、スポンサー受付が開始したらすぐに申し込みましょう。

過去の動画チェック

PyCon JPの過去の動画がYoutubeにあがっています。 価値のあるブースにしたいので、過去の他社のブースの動画などをみて、どういうブースがいいかチームで話し合いました。

準備

具体的に準備を開始しました。

  • ポロシャツ(スタッフ感を出すために地味めのポロシャツに決定)
  • チラシ(スケジュールがギリギリ過ぎてデザイナーがアサインできず、1年目は私の手作りでした。あはは)
  • ポスター(コミケなどで使うポスタースタンドを会社の人が持っていたので借りる)
  • 動画(ブースに流す動画。)
  • ブースに来た人への対応リスト(来た人にする質問などを事前に決める)
  • 当日のスタッフの動きの表(誰がどこにいるかわかって良かったです)
  • 持っていくもののチェックリスト(忘れ物がないか確認)

特に動画は良かったですね。深く考えずに動画を作って、それを写すディスプレイを持っていっていたのですが、本当に役に立ちました。

あと、スタッフっぽいポロシャツもお客様が声をかけやすいので重要です。メンバーの服が揃っていることが重要です。

当日

実際の運営は、会社にPyCon JPに詳しい人が結構いました。 加えて、いつもは会場スタッフとして活躍されている方がいるんですが、その年はスタッフをお休みしていらっしゃいました。ものすごく助けていただけました!!

知り合いに会って話し込んだり、スタッフの中からスピーカーに選ばれる人が出てくるので、思うより1人か2人多めにスタッフはアサインしたほうがいいです。

2017年に至っては、私以外は社長か、スピーカー。朝の集合時間に2日とも自分しかいない状態でした。。。とほほ。。元気で飲みすぎないスピーカーじゃない人のアサイン大事!

いらなかったもの

初年度でいらなかったものも結構ありました。

  • イス(座っている暇がなかった)
  • シール(需要がなかった。サービスが有名になっていないのにシールを欲しがる人はいない。)

通路には結構椅子があるので、人が歩いていない時はそっちに座ればいいだけでした。休憩という名の散歩にも結構行ったので、座る暇はなかったです。

最後に

「1日目に飲みすぎると2日目が地獄」という言葉を皆様に送ります。

unittestの公式ドキュメントを読んでみた

Dec 11, 2017

unittestの公式ドキュメントを読みます。

unittest — ユニットテストフレームワーク

基本的な例

import unittest

# unittest.TestCase)を継承するTestStringMethodsクラスを定義していますね。
class TestStringMethods(unittest.TestCase):

    # 1つ目のテスト
    # 「'foo'.upper()」と「'FOO'」が等しいか比較していますね
    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    # 2つ目のテスト
    # 全部大文字かどうかを確認するstr.isupper()を利用しています
    def test_isupper(self):
        # 「'FOO'.isupper())」の結果がTrueか
        self.assertTrue('FOO'.isupper())
        # 「'Foo'.isupper()」の結果がFalseか
        self.assertFalse('Foo'.isupper())

    # 3つ目のテスト
    # 文字を配列に分割して、比較
    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # わざとstr.split()の引数に文字以外のものを指定して、TypeErrorが起こるか検証
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

if __name__ == '__main__':
    unittest.main()

実行

$ python unittest_sample1.py 
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

-v オプションを付けて詳細を表示

$ python unittest_sample1.py 
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK
(env) Arsenal:tests kaz$ python unittest_sample1.py -v
test_isupper (__main__.TestStringMethods) ... ok
test_split (__main__.TestStringMethods) ... ok
test_upper (__main__.TestStringMethods) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

コマンドラインからも実行できる

$ python -m unittest unittest_sample1.TestStringMethods
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

ファイルパスでもできる

$ python -m unittest unittest_sample1.py 
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

-v オプションも付けられる

$ python -m unittest -v unittest_sample1.TestStringMethods
test_isupper (unittest_sample1.TestStringMethods) ... ok
test_split (unittest_sample1.TestStringMethods) ... ok
test_upper (unittest_sample1.TestStringMethods) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

今日はここまで、公式ドキュメントを読むのも楽しいですね。

doctestを触ってみた

Dec 10, 2017

doctestを触ってみました。

sample.py

"""
値を1増加させる関数です
>>> add_one(1)
2
"""


def add_one(x):
    """
    値が1増加します
    >>> [add_one(x) for x in range(5)]
    [1, 2, 3, 4, 5]
    """
    return x + 1


if __name__ == '__main__':
    import doctest
    doctest.testmod()

実行する

$ python sample.py

正常に動作した場合はなにも表示されない

sample.pyの14行目を return x + 2 と書き換えて実行

$ python sample.py 
**********************************************************************
File "sample.py", line 3, in __main__
Failed example:
    add_one(1)
Expected:
    2
Got:
    3
**********************************************************************
File "sample.py", line 11, in __main__.add_one
Failed example:
    [add_one(x) for x in range(5)]
Expected:
    [1, 2, 3, 4, 5]
Got:
    [2, 3, 4, 5, 6]
**********************************************************************
2 items had failures:
   1 of   1 in __main__
   1 of   1 in __main__.add_one
***Test Failed*** 2 failures.

エーラーが出ます。 正しい場合も実行時にオプション -v をつけるとテストの詳細が表示されます。

$ python sample.py -v
Trying:
    add_one(1)
Expecting:
    2
ok
Trying:
    [add_one(x) for x in range(5)]
Expecting:
    [1, 2, 3, 4, 5]
ok
2 items passed all tests:
   1 tests in __main__
   1 tests in __main__.add_one
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

別のファイルにも書き出せるようです。

sample.txt

The ``sample`` module
==========================
Using ``add_one``
------------------------
First import ``add_one`` from the ``sample`` module:

    >>> from sample9 import add_one

Now use it:

    >>> add_one(1)
    2

sample.py

def add_one(x):
    return x + 1


if __name__ == '__main__':
    import doctest
    doctest.testfile("sample.txt")

実行

$ python sample.py -v
Trying:
    from sample import add_one
Expecting nothing
ok
Trying:
    add_one(1)
Expecting:
    2
ok
1 items passed all tests:
   2 tests in sample.txt
2 tests in 1 items.
2 passed and 0 failed.
Test passed.

簡単な機能の関数のテストならこれで充分ですね。

参考リンク

公式ドキュメント: doctest — 対話的な実行例をテストする

参考図書

Effective Pythonで学ぶ - 4章 メタクラスと属性

Dec 9, 2017

昨日までのあらすじ

Effective Pythonを真面目に読もうと思ったので読みはじめました。

4章 メタクラスと属性

まずは、 メタクラス とはなんでしょうか?

困ったときは、Python文法詳解を読みます。さすが姉妹本です。

class type(name, bases, dict)

組み込み関数の type() を利用すると動的にクラスが作れる。型オブジェクトの型となるようなクラスをメタクラスと呼ぶそうです。へー。

def method(self, arg):
    print(self, arg)


Spam = type('Spam', (), {'ham':method, 'egg':100})

a = Spam()
a.ham(50)
print(a.egg)
print(type(a))
100
<__main__.Spam object at 0x10382d080> 50
<class '__main__.Spam'>

文法はわかりました。 あとで、[Python] メタクラスをたおした - くろのても読みます。

メタクラスは今のところ使わなそうなので飛ばします。ついでに5章の平行性と並列性もいったん飛ばし。



記事一覧