Kuzunoha-NEのブログ

プログラミングなどの勉強をしてます

【Python】1年近くプログラマーやってFizzBuzzの作り方が変わったのさ

こんばんは、葛の葉です。

以前までの作り方

def fizuubuzz(num):
    if num % 15 == 0:
        return 'FizzBuzz!'
    elif num % 3 == 0:
        return 'Fizz!'
    elif num % 5 == 0:
       return 'Buzz!'
    else:
        return str(num)

これからの作り方

ディレクトリを作成する。

├── /app
└── /test

このようにテストと本番を別ける。

testアプリケーションを作成する。

pytestで初期実行するconftest.pyを以下のように作成する。

# conftest.py
import os
import sys
sys.path.append(os.path.abspath(os.path.dirname(
    os.path.abspath(__file__)) + '/../app/'))

これは、テストを実行するときのディレクトリの目線をappにするものです。 import等、ディレクトリを読み込むときはappディレクトリがスタートになります。 カレントディレクトリがappになるといった感じです。

├── /app
└── /test
    └── conftest.py

列挙型で定数を作る

pythonには列挙型であるenumというものがあります。これの整数列挙型であるIntEnumというものを使用します。

app/Numbers.pyというpythonプログラム作成し、以下のようにします。

# Numbers.py
from enum import IntEnum


class Numbers(IntEnum):
    FIZZ = 3
    BUZZ = 5
    FIZZBUZZ = FIZZ * BUZZ

これの説明はtest_Numbers.pyというテストプログラムを作成します。

# test_Numbers.py
from Numbers import Numbers


def test_Numbers():
    assert 3 == Numbers.FIZZ
    assert 5 == Numbers.BUZZ
    assert 15 == Numbers.FIZZBUZZ

testディレクトリをカレントディレクトリにしてから、pytestと実行すれば1 passed in 0.** secondsと表示されるはずです。

======================== test session starts =========================
platform linux -- Python 3.6.6, pytest-3.8.1, py-1.6.0, pluggy-0.7.1
rootdir: /home/kuzunoha/sand_box/test, inifile:
plugins: pylama-7.6.6
collected 1 item                                                     

test/test_Numbers.py .                                         [100%]

====================== 1 passed in 0.02 seconds ======================

Numbers.FIZZ整数3とアサート出来ます。

Numbers.BUZZ整数5とアサート出来ます。

Numbers.FIZZBUZZ整数15とアサート出来ます。

これらNumbers定数のように扱うようにします。

├── /app
│   └── Numbers.py
└── /test
    ├── conftest.py
    └── test_Numbers.py

FizzBuzzを作る。

まずは空のapp/FizzBuzz.pyと空のtest/test_FizzBuzz.pyを作成します。

├── /app
│   ├── FizzBuzz.py
│   └── Numbers.py
└── /test
    ├── conftest.py
    ├── test_FizzBuzz.py
    └── test_Numbers.py

そうしてFizzBuzz.pyを作成します。

# FizzBuzz.py
from Numbers import Numbers


class FizzBuzz(object):
    def checker(self, insert_number):
        return 'Fizz!'

test_FizzBuzz.pyを作成します。

# test_FizzBuzz.py
import pytest

from FizzBuzz import FizzBuzz


@pytest.fixture()
def fizz_buzz():
    # インスタンスを作成
    fizz_buzz = FizzBuzz()
    return fizz_buzz


def test_checker(fizz_buzz):
    assert 'Fizz!' == fizz_buzz.checker(3)

pytest test_checker.pyと実行してパスすればしっかりインポートが成功しています。さて、ここまで作ってようやく、FizzBuzz.pyの実装をいろいろ考えられます。今回はFizzBuzzクラスのcheckerという関数から文字列を返してもらえばいいように考えます。

def test_checker(fizz_buzz):
    assert 'Fizz!' == fizz_buzz.checker(3)
    assert '2' == fizz_buzz.checker(2) # 追加

今の状態ではテストは通りません。テストを通すようにします。

# FizzBuzz.py
from Numbers import Numbers


class FizzBuzz(object):
    def checker(self, insert_number: int) -> str:
        if insert_number % Numbers.FIZZBUZZ == 0:
            return 'FizzBuzz!'
        elif insert_number % Numbers.FIZZ == 0:
            return 'Fizz!'
        elif insert_number % Numbers.BUZZ == 0:
            return 'Buzz!'
        else:
            return str(insert_number)

pytestを行う

===================== test session starts ======================
platform linux -- Python 3.6.6, pytest-3.8.1, py-1.6.0, pluggy-0.7.1
rootdir: /home/kuzunoha/sand_box/test, inifile:
plugins: pylama-7.6.6
collected 2 items                                              

test/test_FizzBuzz.py .                                  [ 50%]
test/test_Numbers.py .                                   [100%]

=================== 2 passed in 0.03 seconds ===================

テストする項目を増やしてみる。

# test_FizzBuzz.py
import pytest

from FizzBuzz import FizzBuzz


@pytest.fixture()
def fizz_buzz():
    # インスタンスを作成
    fizz_buzz = FizzBuzz()
    return fizz_buzz


def test_checker(fizz_buzz):
    assert 'Fizz!' == fizz_buzz.checker(3)
    assert '2' == fizz_buzz.checker(2)
    assert 'Buzz!' == fizz_buzz.checker(5)
    assert 'FizzBuzz!' == fizz_buzz.checker(15)
    assert 'FizzBuzz!' == fizz_buzz.checker(30)
======================== test session starts =========================
platform linux -- Python 3.6.6, pytest-3.8.1, py-1.6.0, pluggy-0.7.1
rootdir: /home/kuzunoha/sand_box/test, inifile:
plugins: pylama-7.6.6
collected 2 items                                                    

test/test_FizzBuzz.py .                                        [ 50%]
test/test_Numbers.py .                                         [100%]

====================== 2 passed in 0.03 seconds ======================

もっともっと勉強が必要

がんばらないと