(初心者向け)Python3のunittestで軽くハマったので記事書く

ググってやってみたけど、いろいろとハマりポイントあったので参考までに書きます
クラスがある場合、クラスがない場合それぞれのユニットテスト.

unittest : Pythonの標準テスト機構。
import unittest って書くだけで使える。


###テストしたいファイル###
calc.py :計算結果を返してくれるモジュール
say.py  :聴衆が叫んでくれるモジュール

##成功例(コピペすれば実行できます)##
###ファイル構成###

```
python
┣ Actual(実際のコード)
┃   ┣ __init__.py ハマりポイント1で解説
┃   ┣ calc.py (クラスがないファイル)
┃   ┗ say.py  (クラスがあるファイル)
┗ Test(テストコード)
    ┣ __init__.py ハマりポイント1で解説
    ┗ testSayAndCalc.py (ほんとはファイルごとに分けるべき)
```

###実際のファイル###

```python:__init__.py
#中身空でOK
```


```python:calc.py
def hikizan(a,b):
    return a-b
```

```python:say.py
class Hoge:
    def sayFoo(self):
        return "audience:Foo"
    def say(self,a,b):
        return "audience:" + a+b
```

```python:testSayAndCalc.py
from unittest import TestCase
from Actual.say import Hoge

import os
import sys
path = os.path.join(os.path.dirname(__file__), '../')
sys.path.append(path)
import Actual.calc

class unittest(TestCase):
    def test_say(self):
        self.assertEqual(Hoge.sayFoo(self), 'audience:Foo')
        #ココだけわざと間違えてるのでテストエラーになる予定
        self.assertEqual(Hoge.say(self,"Yo","Ho"),"audience:YooHo")
    
    def test_calc(self):
        self.assertEqual(Actual.calc.hikizan(4,3),1)

```

###実行方法###

```terminal:terminal(コマンドプロンプト)
PS C:python> python -m unittest Test.testSayAndCalc
```
###実行結果###

```terminal:terminal(コマンドプロンプト)
.F
======================================================================
FAIL: test_say (Test.testSayAndCalc.unittest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:python\Test\testSayAndCalc.py", line 14, in test_say
    self.assertEqual(Hoge.say(self,"Yo","Ho"),"audience:YooHo")
AssertionError: 'audience:YoHo' != 'audience:YooHo'
- audience:YoHo
+ audience:YooHo
?            +
```

無事、テストを走らせることができました。

##ハマりポイント##
###ハマりポイント1: 別階層のモジュールimportができない###

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そして他階層にあるモジュールのインポートは容易にはできないのか<a href="https://t.co/kP2SuJuCxw">https://t.co/kP2SuJuCxw</a></p>&mdash; 筋Tech (@workoutholic1) <a href="https://twitter.com/workoutholic1/status/1063720451208228865?ref_src=twsrc%5Etfw">2018年11月17日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

別階層のモジュールを読み込む場合、import元と先に
1. \_\_init__.py を配置
2. import前に以下を書き込む

```
import os
import sys
path = os.path.join(os.path.dirname(__file__), '../')
sys.path.append(path)
import Actual.calc(importしたいモジュールを親階層から書く) 
```

###ハマりポイント2: いつものpython XXX.py では実行できない ###
いつものように実行するとエラーになります。
1. 親階層に行く[ファイル構成](https://qiita.com/qwertytoki/items/50284b0917a0baaaf533#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E6%A7%8B%E6%88%90) の場合、pythonディレクトリ以下でコマンドを打つ必要があります
2. ```python -m unittest Test.testSayAndCalc``` でテスト実行する 
Testディレクトリ内すべてのテストを実行したい場合は ```python -m unittest discover Test```

クラスがうまくimportできない、とか、
Module 'unittest' has no 'main' member
Module 'unittest' has no 'Testcase' member
などいろいろエラーでたが、[成功例(コピペすれば実行できます)](https://qiita.com/qwertytoki/items/50284b0917a0baaaf533#%E6%88%90%E5%8A%9F%E4%BE%8B%E3%82%B3%E3%83%94%E3%83%9A%E3%81%99%E3%82%8C%E3%81%B0%E5%AE%9F%E8%A1%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99) をきちんとコピペすれば解消できるはず。

以上となります