pythonのunittestメモ

unittest とは

docs.python.org

pythonユニットテストをするための標準モジュールのこと。

ちなみに、pythonで関数やクラスの挙動をテストする方法として、doctest モジュールもあるが、こちらは docstring を用いて記述するものであり、あまり複雑なテストは行えない。むしろ、具体的な使用方法などを記述する目的で使用する事が多い(気がする)。

基本的な使い方

unittestを使うシンプルな例(source

import unittest  # unittestをインポート

# unittest.TestCaseを継承して、自作クラスを定義
class TestStringMethods(unittest.TestCase):

    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')  # イコールかどうかを検証

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())  # Trueかどうかを検証
        self.assertFalse('Foo'.isupper())  # Falseかどうかを検証

    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])

        # s.splitのセパレータが非stringの場合を確認
        with self.assertRaises(TypeError):
            s.split(2)

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

テストコードを書く手順は、

  1. unittest をインポート
  2. unittest.TestCase を継承したクラスを定義
  3. クラスに、test[任意] メソッドを追加し、そこに検証するべき assert[任意] を書く
  4. unittest.main()を呼ぶ

注意

クラス名は任意でOKだが、メソッド名は 必ず test[任意] にしなければならない。例 test_hoge, test_fuga
また、assert[任意] はアサートメソッドであり、
例えば

  • ab がイコールかどうかを検証したい場合
    • assertEqual(a, b)
  • x が True かどうかを検証したい場合
    • assertTrue(x)
  • x が False かどうかを検証したい場合
    • assertFalse(x)

と書く。すべてのアサートメソッドは以下の通りである。

アサートメソッド 確認事項
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
assertIsInstance(a, b) isinstance(a, b)
assertNotIsInstance(a, b) not isinstance(a, b)

source

上のアサートメソッドでは、変数や処理結果の 等価/非等価 や、真/偽を確認することはできるが、例外発生を確認することはできない(下記を参照)。

例外が発生することを確認したい

with assertRaises(予期される例外) でチェックしたい処理を囲む。

import unittest

class MyTest(unittest.TestCase):
    
    # 文字列と整数の加算演算はTypeErrorになる
    def test_type_error(self):
        with self.assertRaises(TypeError):
            'string' + 1

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

複数の値を連続でテストしたい

繰り返し処理の中身でテストしたい場合のテストの書き方。サブテスト を利用する

例えば、2つのリストの中身が 順序も含めて 等しいかを確認したい場合。

ref_list = [1, 4, 3, 5, 7]
ok_list = [1, 4, 3, 5, 7]
ng_list = [1, 4, 5, 3, 7]  # 3 と 5 が入れ替わってる

普通に比較するだけだと、TrueかFalseしかわからない

print(ref_list == ok_list)
# True
print(ref_list == ng_list)
# False

サブテストを使って確認する

import unittest

class ListTest(unittest.TestCase):

    # 実際の処理を行うメソッド
    def all_equal(self, msg, list_a, list_b):
        for a, b in zip(list_a, list_b):
            with self.subTest(msg, ref=a, target=b):
                self.assertEqual(a, b)

    # OKの場合のテスト
    def test_OK(self):
        ref_list = [1, 4, 3, 5, 7]
        ok_list  = [1, 4, 3, 5, 7]
        return self.all_equal('たぶん OK', ref_list, ok_list)

   # NGのばあいのテスト
    def test_NG(self):
        ref_list = [1, 4, 3, 5, 7]
        ng_list  = [1, 4, 5, 3, 7]  # 3 と 5 が入れ替わってる
        return self.all_equal('たぶん NG', ref_list, ng_list)


if __name__ == '__main__':
    unittest.main()
test_NG (__main__.ListTest) ... test_OK (__main__.ListTest) ... ok

======================================================================
FAIL: test_NG (__main__.ListTest) [たぶん NG] (ref=3, target=5)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "e03.py", line 8, in all_equal
    self.assertEqual(a, b)
AssertionError: 3 != 5

======================================================================
FAIL: test_NG (__main__.ListTest) [たぶん NG] (ref=5, target=3)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "e03.py", line 8, in all_equal
    self.assertEqual(a, b)
AssertionError: 5 != 3

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=2)

3と5が入れ替わってることがわかる。失敗した回数も教えてくれる。

subTest の引数は1つめにメッセージ、2つめ以降にサブテストが失敗した場合に表示したいものを入れる。 source

Vueをはじめます

このブログの目的

自分が何をしたかを残しておきたいので、はじめました。 完全に自分用です。 基本的にやったことを列挙していって、思ったことを書きなぐる感じで行きます。

Vueの公式チュートリアルを眺めた

jp.vuejs.org

とりあえず眺めたが、専門用語すぎて言ってる事がよくわからない。

何もわからなかったので、いつものように Qiita のお世話になることに…

QiitaにあったVue.jsチュートリアルを触る

qiita.com

触りました。

nodeとnpmはNLP100本ノックをnodeで解こうと試みた背景があって、導入済みでした

% node -v
v10.15.1

% npm -v
6.4.1

プロジェクトの作成

% npm init
% npm install vue-cli
% npx vue --version
2.9.6

とりあえず何もわからないので、全てYes!!

% npx vue init webpack tutorial_vuejs_todo_management

? Project name tutorial_vuejs_todo_management
? Project description A Vue.js project
? Author KamuiRoeru <me1802@s.akashi.ac.jp>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Set up unit tests Yes
? Pick a test runner jest
? Setup e2e tests with Nightwatch? Yes
? Should we run `npm install` for you after the project has been created? (recommended) npm

とりあえず実行!!!

% cd tutorial_vuejs_todo_management
% npm install
% npm run dev

うごいた。

githubにあげとくと楽らしいので、適当に作っておきました。

% git init
% git add .
% git commit -m "initial commit"
% git remote add https://github.com/kamuiroeru/tutorial_vuejs_todo_management.git
% git push origin master

github.com

依存関係の脆弱性

なんか警告出てる…

f:id:kamuiroeru:20190508191009p:plain
警告

調べると、なんかパッケージのバージョンが古くて脆弱性ありありだそうで。

webpack-dev-server がやばいらしい。

www.l08084.com

解消します。

% npm install -g npm-check-updates
% ncu
# 中略
 webpack-dev-server                               ^2.9.1  →     ^3.3.1
# 中略

めっちゃ出てきた…

% ncu -u
% rm -rf package-lock.json
% npm update

% ncu
All dependencies match the latest package versions :)

警告消えたやったぜ!

ファイル構成を眺める

特にこだわりはないのですが、WebStormで眺めた。

  • <template>で html
  • <script>javascript
  • <style scoped> で このスコープだけの CSS

を書いたやつが .vueファイルなんだな〜

コンポーネントがよくわからなかったので公式ページ見た。 ちょっとだけわかった気がする。

jp.vuejs.org

まとめ

次やりたいこと

  • Vueインスタンスについて何もわからないので、公式ページを参考に理解していきたい。