いろいろな言語の単体テスト書いてみた

# レポジトリ
[Github](https://github.com/syuchan1005/UnitTestExamples) にて下で紹介しているものを公開しています。

# はじめに
いろいろな言語に触れてみようと思いたち、試しに簡単な単体テストを書いてみる。
詳細な解説はしないのでそれについては外部のdocを参照してほしい。

~~～～は各IDEを用いることで簡単に実行できるため、コマンドラインでの実行は不要とし記述しない。とか書いてあるのはただの知識不足です~~

また全てWindown 10 Pro Insider Preview Build 17025上で実行している。

# Python
## 実行環境
Python 3.6.1

## 概要
Pythonでは標準で'unittest'パッケージが利用可能なので利用する。

## ファイル
```
Python/
　├ src/
　│　└ sample.py
　├ test/
　│　└ sample_test.py
　└ setup.py
```

sample.py

```py:sample.py
class Calc:
    def add(self, x, y):
        return x + y

    def pow(self, x, y):
        return x ** y

```

sample_test.py

```py:sample_test.py
import sys
import unittest

from sample import Calc


class TestSample(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.calc = Calc()

    def test_add(self):
        self.assertEqual(15, self.calc.add(10, 5))
        self.assertEqual(5, self.calc.add(8, -3))

    def test_pow(self):
        self.assertEqual(125, self.calc.pow(5, 3))
        self.assertEqual(sys.maxsize, self.calc.pow(2, 31) - 1)

```

setup.py

```py:setup.py
from setuptools import setup, find_packages
import sys
import unittest

# 開発時でもpip install -e . のようにしておくと、どのファイルからでもsampleモジュールを参照できる
# その場合は、以下のsys.path.appendは不要になります。
sys.path.append('./src')


def my_test_suite():
    """testディレクトリ以下の、*_test.pyをテストモジュールとして認識する"""
    test_loader = unittest.TestLoader()
    test_suite = test_loader.discover('test', pattern='*_test.py')
    return test_suite


setup(
    name="Sample",
    version="1.0",
    # srcをルートとする場合でpipに対応させるならば、例えば以下のように設定
    package_dir={'': 'src'},
    packages=find_packages('src'),

    test_suite='setup.my_test_suite'
)

```

## 実行方法
`python setup.py test`をターミナルより実行。

## doctestを使ったテストの例
```py:sample.py
"""doctestの例

このモジュールを直接実行で、doctestが開始されます。
失敗したテストがあれば、

File "sample.py", line 11, in __main__
Failed example:
    calc.pow(5, 3)
Expected:
    126
Got:
    125
**********************************************************************
1 items had failures:
   1 of   4 in __main__
***Test Failed*** 1 failures.
のように表示されます。

>>> calc = Calc()
>>> calc.add(10, 5)
15
>>> calc.add(8, -3)
5
>>> calc.pow(5, 3)
126

"""

class Calc:
    def add(self, x, y):
        return x + y

    def pow(self, x, y):
        return x ** y


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


```

# Java
## 実行環境
Java 9
JUnit 5

## 概要
Javaには様々な単体ライブラリがあるが有名なJUnitを利用する。

## ファイル
```
Java/
　├ src/
　│　└ Calc.java
　└ test/
   　└ CalcTest.java
```

Calc.java

```java:Calc.java
public class Calc {
	public int add(int x, int y) {
		return x + y;
	}

	public double pow(int x, int y) {
		return Math.pow(x, y);
	}
}
```

CalcTest.java

```java:CalcTest.java
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class CalcTest {
	private Calc calc = new Calc();

	@Test
	void add() {
		assertEquals(15, calc.add(10, 5));
		assertEquals(5, calc.add(8, -3));
	}

	@Test
	void pow() {
		assertEquals(125, calc.pow(5, 3));
		assertEquals(Integer.MAX_VALUE, calc.pow(2, 31) - 1);
	}

}
```

## 実行方法
JUnitは各IDEを用いることで簡単に実行できるため、コマンドラインでの実行は不要とし記述しない。

# JavaScript(Node.js)
## 実行環境
NodeJS v8.6.0
npm v5.3.0

## 概要
様々なライブラリがあるが今回はmochaを利用する。
class構文を扱うためbabel-cli及びbabel-preset-envを利用した。

## ファイル
```
NodeJS/
　├ src/
　│　└ Calc.js
　├ test/
　│　└ calc.spec.js
　└ package.json
```

Calc.js

```js:Calc.js
class Calc {
	add(x, y) {
		return x + y;
	}

	pow(x, y) {
		return Math.pow(x, y);
	}
}

export default Calc
```

calc.spec.js

```js:calc.spec.js
import Calc from '../src/Calc';

const assert = require('assert');

describe('Calc', () => {
	const calc = new Calc();

	describe('add()', () => {
		assert.equal(15, calc.add(10, 5));
		assert.equal(5, calc.add(8, -3));
	});

	describe('pow', () => {
		assert.equal(125, calc.pow(5, 3));
		assert.equal(0x7FFFFFFF, calc.pow(2, 31) - 1);
	});
});
```

package.json

```json:package.json
// 中略
　"scripts": {
    "test": "mocha --compilers js:babel-register --recursive $(find test -name '*.spec.js')"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-preset-env": "^1.6.1",
    "mocha": "^4.0.1"
  },
  "babel": {
    "presets": [
      "env"
    ]
  }
```

## 実行方法
NodeJSフォルダ内にて`npm test`を実行する。

# PHP
## 実行環境
PHP 7.1.0

## 概要
様々なライブラリがあるが今回はPHPUnitを利用する。

## ファイル
```
PHP/
　├ src/
　│　├ autoload.php
　│　└ Calc.php
　├ tests/
　│　└ CalcTest.php
　├ composer.json
　└ phpunit.xml
```

autoload.php

```php:autoload.php
<?php
require_once "Calc.php";
```

Calc.php

```php:Calc.php
<?php
namespace Sample;

class Calc
{
    public function add($x, $y)
    {
        return $x + $y;
    }

    public function pow($x, $y)
    {
        return $x ** $y;
    }
}
```

CalcTest.php

```php:CalcTest.php
<?php
namespace Sample;

use PHPUnit\Framework\TestCase;

class CalcTest extends TestCase
{
    public $calc;

    function __construct($name = null, array $data = [], $dataName = '')
    {
        parent::__construct($name, $data, $dataName);
        $this->calc = new Calc();
    }

    public function testAdd()
    {
        $this->assertEquals(15, $this->calc->add(10, 5));
        $this->assertEquals(5, $this->calc->add(8, -3));
    }

    public function testPow()
    {
        $this->assertEquals(125, $this->calc->pow(5, 3));
        $this->assertEquals(0x7FFFFFFF, $this->calc->pow(2, 31) - 1);
    }
}
```

composer.json

```json:composer.json
{
  // 中略
  "require": {
    "phpunit/phpunit": "6.4.4"
  }
}

```

phpunit.php

```php:phpunit.php
<phpunit bootstrap="src/autoload.php">
    <testsuites>
        <testsuite name="calc">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
</phpunit>
```

## 実行方法
PHPUnitは各IDEを用いることで簡単に実行できるため、コマンドラインでの実行は不要とし記述しない。

# Go
## 実行環境
Go 1.9.2

## 概要
Goには標準で`testing`パッケージがあるので利用する。
~~最初assertなんたら系無いのかと思ったけどちゃんと理由があって納得した~~

## ファイル
```
Go/
　└ src/
　 　└ sample/
　 　 　├ calc.go
　 　 　└ calc_test.go
```

calc.go

```go:calc.go
package sample

import (
	"math"
)

type Calc struct {}

func (calc *Calc) Add(x, y int) int {
	return x + y
}

func (calc *Calc) Pow(x, y float64) float64 {
	return math.Pow(x, y)
}
```

calc_test.go

```go:calc_test.go
package sample_test

import (
	"testing"
	c "."
)

var calc = c.Calc{}

func TestCalc_Add(t *testing.T) {
	if calc.Add(10, 5) != 15 {
		t.Error("Add Failed");
	}
	if calc.Add(8, -3) != 5 {
		t.Error("Add Failed");
	}
}

func TestCalc_Pow(t *testing.T) {
	if calc.Pow(5, 3) != 125 {
		t.Error("Pow Failed");
	}
	if calc.Pow(2, 31) - 1 != 0x7FFFFFFF {
		t.Error("Pow Failed");
	}
}

```

## 実行方法
Goディレクトリ内にて`go test ./src/sample/calc_test.go
`を実行する。

# 最後に
いろいろな言語に触れてみたいので増やすかもしれない(リクエストも募集)