空飛ぶロボットのつくりかた

ロボットをつくるために必要な技術をまとめます。ロボットの未来についても考えたりします。

pythonのテストを書いてみる2

数値微分

プロダクションコード

# -*- coding:utf-8 -*-                                                          

# 2次関数の数値微分を行うクラス                                                 
class Diff:
    # 2次関数                                                                   
    def f(self,x):
        y = x**2
        return y

    # 数値微分                                                                  
    def numerical_diff(self,f,x,dx):
        if dx == 0:
            raise ValueError('division by zero')
        else:
            x_diff = (f(x+dx)-f(x-dx))/(2*dx)
            return x_diff

if __name__ == '__main__':
    diff = Diff()
    print diff.numerical_diff(diff.f,3,0.001)

テストコード

# -*- coding:utf-8 -*-                                                 
import unittest, numerical_diff

class TestDiff(unittest.TestCase):
    # 前処理                                                           
    def setUp(self):
        self.diff = numerical_diff.Diff()

    # 後片付け                                                         
    def tearDowm(self):
        pass

    # 3の2乗のテスト                                                   
    def test_func1(self):
        self.assertEqual(self.diff.f(3),9)

    # 4の2乗のテスト                                                   
    def test_func2(self):
        self.assertEqual(self.diff.f(4),16)

    # 数値微分ができているかのテスト                                   
    def test_numerical_diff(self):
        self.assertAlmostEqual(self.diff.numerical_diff(self.diff.f,3,0.001),6.0, delta=1e-8)
        self.assertEqual(round(self.diff.numerical_diff(self.diff.f,3,0.001)),6.0) # ダメな例。検証したい値に操作を加えている。

    # 0で割られたときの例外のテスト                                    
    def test_numerical_diff_zero_error(self):
        with self.assertRaises(ValueError) as cm:
            self.diff.numerical_diff(self.diff.f,3,0.0)
        exception = cm.exception
        self.assertEqual(exception.message, 'division by zero')

文字の変換

プロダクションコード

#-*- coding:utf-8 -*-
import re

class StringUtils:
    def to_snake_case(self,text):
        if len(text) is 0:
            raise ValueError('snake case error')
        else:
            snake = re.sub("([A-Z])",lambda x:"_" + x.group(1).lower(),text)
            return re.sub("^_","",snake)

    def to_camel_case(self,text):
        if len(text) is 0:
            raise ValueError('camel case error')
        else:
            camel = re.sub("_(.)",lambda x:x.group(1).upper(),text)
            return re.sub("^(.)",lambda x:x.group(1).upper(),camel)

if __name__ == '__main__':
    camel = "CamelCase"
    snake = "snake_case"
    string_utils = StringUtils()
    print string_utils.to_snake_case(camel)
    print string_utils.to_camel_case(snake)

参考: lambda式はすごく面白い - 元理系院生の新入社員がPythonとJavaで色々頑張るブログ

【技術】pythonでのキャメルケースとスネークケースの変換について - エンジニアリングとお金の話

Pythonで文字列を置換する:replace(), re.sub() | UX MILK

テストコード

# -*- coding:utf-8 -*-
import unittest, string_utils

class TestStringUtils(unittest.TestCase):
    # 前処理
    def setUp(self):
        self.su = string_utils.StringUtils()

    # 後片付け
    def tearDowm(self):
        pass

    # camel->snake, snake->camelへの変換テスト
    def test_to_snake_case1(self):
        self.assertEqual(self.su.to_snake_case("CamelCase"),"camel_case")

    def test_to_snake_case2(self):
        self.assertEqual(self.su.to_snake_case("camelCase"),"camel_case")

    def test_to_snake_case3(self):
        self.assertEqual(self.su.to_snake_case("camelcase"),"camelcase")

    def test_to_camel_case1(self):
        self.assertEqual(self.su.to_camel_case("snake_case"),"SnakeCase")

    def test_to_camel_case2(self):
        self.assertEqual(self.su.to_camel_case("Snake_Case"),"SnakeCase")

    def test_to_camel_case3(self):
        self.assertEqual(self.su.to_camel_case("SnakeCase"),"SnakeCase")


    # 文字がない場合の例外のテスト
    def test_snake_error(self):
        with self.assertRaises(ValueError) as cm:
            self.su.to_snake_case("")
        exception = cm.exception
        self.assertEqual(exception.message, 'snake case error')

    def test_camel_error(self):
        with self.assertRaises(ValueError) as cm:
            self.su.to_camel_case("")
        exception = cm.exception
        self.assertEqual(exception.message, 'camel case error')

カウント

プロダクションコード

# -*- coding:utf-8 -*-

class Counter:
    def __init__(self):
        self.count = 0
    def increment(self):
        self.count += 1
        return self.count

if __name__ == '__main__':
    counter = Counter()
    for i in range(10):
        print counter.increment()

テストコード

# -*- coding:utf-8 -*-
import unittest, counter

class TestCounter(unittest.TestCase):
    # 前処理
    def setUp(self):
        self.ct = counter.Counter()

    # 後片付け
    def tearDowm(self):
        pass

    # カウントできているかのテスト
    def test_count_init(self):
        self.assertEqual(self.ct.increment(),1)

    def test_count_2(self):
        self.ct.increment()
        self.assertEqual(self.ct.increment(),2)

    def test_count_100(self):
        for i in range(100):
            self.ct.increment()
        self.assertEqual(self.ct.increment(),101)

偶数判定

プロダクションコード

# -*- coding:utf-8 -*-

class NumberUtils:
    def even(self,num):
        return num % 2 == 0

if __name__ == '__main__':
    number = NumberUtils()
    print number.even(2)
    print number.even(3)

テストコード

# -*- coding:utf-8 -*-
import unittest, number_utils

class TestStringUtils(unittest.TestCase):
    # 前処理
    def setUp(self):
        self.nu = number_utils.NumberUtils()

    # 後片付け
    def tearDowm(self):
        pass

    def test_even(self):
        self.assertTrue(self.nu.even(2))

    def test_odd(self):
        self.assertFalse(self.nu.even(3))

物品管理

プロダクションコード

# -*- coding:utf-8 -*-

class Item:
    def __init__(self,name,price):
        self.name = name
        self.price = price

    def get_name(self):
        return self.name

    def get_price(self):
        return self.price

class ItemStock:
    def __init__(self):
        self.item_dic = {}

    def add(self, item):
        num = self.item_dic.get(item.name)
        if num is None:
            num = 0
        num +=1
        self.item_dic[item.name] = num

    def get_num(self, item):
        num = self.item_dic.get(item.name)
        if num is not None:
            return num
        else:
            return 0

if __name__ == '__main__':
    drone = Item("drone",6800)
    robot = Item("robot",10000)
    item_stock = ItemStock()
    item_stock.add(drone)
    item_stock.add(drone)
    item_stock.add(robot)
    print drone.get_name(),drone.get_price()
    print item_stock.get_num(drone)
    print robot.get_name(),robot.get_price()
    print item_stock.get_num(robot)

テストコード

# -*- coding:utf-8 -*-
import unittest, item_stock

class TestItemSocket(unittest.TestCase):
    # 前処理
    def setUp(self):
        self.itemstock = item_stock.ItemStock()
        self.drone = item_stock.Item("drone",6800)
        self.robot = item_stock.Item("robot",10000)

    # 後片付け
    def tearDowm(self):
        pass

    def test_init(self):
        self.assertEqual(self.itemstock.get_num(self.drone),0)

    def test_one_object_add_1(self):
        self.itemstock.add(self.drone)
        self.assertEqual(self.itemstock.get_num(self.drone),1)

    def test_one_object_add_2(self):
        self.itemstock.add(self.drone)
        self.itemstock.add(self.drone)
        self.assertEqual(self.itemstock.get_num(self.drone),2)

    def test_two_object_add_2_and_1(self):
        self.itemstock.add(self.drone)
        self.itemstock.add(self.drone)
        self.itemstock.add(self.robot)
        self.assertEqual(self.itemstock.get_num(self.drone),2)
        self.assertEqual(self.itemstock.get_num(self.robot),1)

スレッド

(TBD)

プロダクションコード

テストコード

FizzBuzz

プロダクションコード

# -*- coding:utf-8 -*-

class FizzBuzz:
    def __init__(self):
        pass

    def create_fizz_buzz_list(self,size):
        list = []
        for i in range(1,size):
            if i % 15 == 0:
                list.append("FizzBuzz")
            elif i % 3 == 0:
                list.append("Fizz")
            elif i % 5 == 0:
                list.append("Buzz")
            else:
                list.append(str(i))
        return list

if __name__ == '__main__':
    fizzbuzz = FizzBuzz()
    print fizzbuzz.create_fizz_buzz_list(20)

テストコード

# -*- coding:utf-8 -*-
import unittest, FizzBuzz

class TestFizzBuzz(unittest.TestCase):
    # 前処理
    def setUp(self):
        self.cfb = FizzBuzz.FizzBuzz()

    # 後片付け
    def tearDowm(self):
        pass

    # FizzBuzzのテスト
    def test_fizz_buzz(self):
        actual = self.cfb.create_fizz_buzz_list(17)
        self.assertEqual(len(actual),16)
        self.assertEqual(actual[0],"1")
        self.assertEqual(actual[1],"2")
        self.assertEqual(actual[2],"Fizz")
        self.assertEqual(actual[3],"4")
        self.assertEqual(actual[4],"Buzz")
        self.assertEqual(actual[5],"Fizz")
        self.assertEqual(actual[6],"7")
        self.assertEqual(actual[7],"8")
        self.assertEqual(actual[8],"Fizz")
        self.assertEqual(actual[9],"Buzz")
        self.assertEqual(actual[10],"11")
        self.assertEqual(actual[11],"Fizz")
        self.assertEqual(actual[12],"13")
        self.assertEqual(actual[13],"14")
        self.assertEqual(actual[14],"FizzBuzz")
        self.assertEqual(actual[15],"16")

ゴリゴリすぎるので、カスタムMatcherでも書いてみたい。。。 (TBD)

カスタムMatcher: Python: Matcher フレームワーク PyHamcrest を使ってみる | CUBE SUGAR STORAGE  GitHub - hamcrest/PyHamcrest: Hamcrest matchers for Python

参考

Python コメント、Pydoc - @//メモ Pythonで学ぶ 基礎からのプログラミング入門 (32) マルチスレッド処理を理解しよう(前編) | マイナビニュース

robonchu.hatenablog.com