2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Pythonのunittestを並列実行する

Posted at

概要

やりたいこと:
Python標準のunittestモジュールを利用したテストコードを並列実行したい

やりかた:
テストランナーとして nose を使い、 --processes オプションで並列実行数を指定する

確認環境

$ python --version
Python 3.7.2
$ nosetests --version
nosetests version 1.3.7

確認用サンプルコード

ここでは並列実行の効果を見たいので、time.sleep() でテストメソッドに1秒の待ちを入れておく。

$ cat test_s1.py
import unittest
import time
class Test(unittest.TestCase):
    def test_method(self):
        time.sleep(1)
        self.assertTrue(True)
$ cat test_f1.py
import unittest
import time
class Test(unittest.TestCase):
    def test_method(self):
        time.sleep(1)
        self.assertFalse("ヒャッハー")
$ ls
test_f1.py  test_s1.py
$ cp test_s{1,2}.py
$ cp test_s{1,3}.py
$ ls
test_f1.py  test_s1.py  test_s2.py test_s3.py

標準のテストランナーを使う

シーケンシャルに実行されるので4秒かかる

$ python -m unittest
F...
======================================================================
FAIL: test_method (test_f1.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/yoichi/prog/python-study/nose/test_f1.py", line 6, in test_method
    self.assertFalse("ヒャッハー")
AssertionError: 'ヒャッハー' is not false

----------------------------------------------------------------------
Ran 4 tests in 4.024s

FAILED (failures=1)

nosetests オプションなし

$ nosetests
F...
======================================================================
FAIL: test_method (test_f1.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/yoichi/prog/python-study/nose/test_f1.py", line 6, in test_method
    self.assertFalse("ヒャッハー")
AssertionError: 'ヒャッハー' is not false

----------------------------------------------------------------------
Ran 4 tests in 4.066s

FAILED (failures=1)

https://nose.readthedocs.io/en/latest/plugins/multiprocess.html より、デフォルトは並列実行しないので想定どおり。

--processes=NUM
  Spread test run among this many processes. Set a number equal to the number
  of processors or cores in your machine for best results. Pass a negative
  number to have the number of processes automatically set to the number of
  cores. Passing 0 means to disable parallel testing. Default is 0 unless
  NOSE_PROCESSES is set. 

nosetests で並列実行

2並列だと2秒で終わる

$ nosetests --processes=2
F...
======================================================================
FAIL: test_method (test_f1.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/yoichi/prog/python-study/nose/test_f1.py", line 6, in test_method
    self.assertFalse("ヒャッハー")
AssertionError: 'ヒャッハー' is not false

----------------------------------------------------------------------
Ran 4 tests in 2.090s

FAILED (failures=1)

4並列だと1秒で終わる

$ nosetests --processes=4
F...
======================================================================
FAIL: test_method (test_f1.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/yoichi/prog/python-study/nose/test_f1.py", line 6, in test_method
    self.assertFalse("ヒャッハー")
AssertionError: 'ヒャッハー' is not false

----------------------------------------------------------------------
Ran 4 tests in 1.128s

FAILED (failures=1)

並列数を上げるとそれだけ同時利用するリソースが増えるので、実行環境に応じて適当な値を設定しましょう。

並列実行の単位

複数のTestCase

一つのファイルに複数のTestCaseクラスがある場合も並列実行してくれる

$ cat test_s1.py
import unittest
import time
class Test1(unittest.TestCase):
    def test_method1(self):
        time.sleep(1)
        self.assertTrue(True)
class Test2(unittest.TestCase):
    def test_method1(self):
        time.sleep(1)
        self.assertTrue(True)
$ ls
test_s1.py
$ nosetests --processes=2
..
----------------------------------------------------------------------
Ran 2 tests in 1.073s

OK

複数のテストメソッド

メソッド単位での並列実行はしてくれない

$ cat test_s1.py
import unittest
import time
class Test1(unittest.TestCase):
    def test_method1(self):
        time.sleep(1)
        self.assertTrue(True)
    def test_method2(self):
        time.sleep(1)
        self.assertTrue(True)
$ ls
test_s1.py
$ nosetests --processes=2
..
----------------------------------------------------------------------
Ran 2 tests in 2.073s

OK
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?