7.27.2015

Python unittest Cheat Sheet

Python: unittest のチートシート

よく使うイディオムをまとめておく。

Python unittest Cheat Sheet

Skeleton

import sys
if sys.version_info < (2, 7):
    import unittest2 as unittest
else:
    import unittest

class TestXxx(unittest.TestCase):

    def setUp(self):
        ...

    def tearDown(self):
        ...

    def test_yyy_description1(self):
        ...
        
    def test_yyy_description2(self):
        ...

Basic tests

self.assertTrue(1 + 2 == 3)
self.assertFalse(1 + 2 == 4)
self.assertEqual(actual, expected)
self.assertNotEqual(actual, not_expected)
self.assertIn('b', ['a', 'b', 'c'])

Test for expected exception

self.assertRaises(ValueError, your_func, arg1, arg2)
with self.assertRaises(SomeException) as cm:
    do_something()

the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)

e.g. Function for testing exit code

def _assert_system_exit(self, expected_code, f):
    with self.assertRaises(SystemExit) as cm:
        f()
    if isinstance(cm.exception, int):
        self.assertEqual(cm.exception, expected_code)
    else:
        self.assertEqual(cm.exception.code, expected_code)
self.assertRaisesRegexp(ValueError, 'invalid literal for.*XYZ$', int, 'XYZ')

Asserting stdout

Prepare helper function.

import sys
from contextlib import contextmanager
from StringIO import StringIO


@contextmanager
def captured_output():
    new_out, new_err = StringIO(), StringIO()
    old_out, old_err = sys.stdout, sys.stderr
    try:
        sys.stdout, sys.stderr = new_out, new_err
        yield sys.stdout, sys.stderr
    finally:
        sys.stdout, sys.stderr = old_out, old_err

Then, in the test code...

with captured_output() as (out, err):
    ...

lines = out.getvalue().splitlines()
self.assertIn('xxx', lines)

Skipping test

@unittest.skip("demonstrating skipping")
def test_nothing(self):
    self.fail("never happens")
  • Python 2.6 に対応するには、unittest2 を使うのが一番簡単

7.20.2015

Dragon Quest 5 (PS2) Time Attack - 2:53

PS2版ドラゴンクエスト5のタイムアタック

 

遠い昔、プレイステーション2 版の ドラゴンクエスト5 で遊んでいた頃のノートがつい先日出てきた。

折角なので、Github にラップタイムをまとめておく。

7.12.2015

Safe and Smart Memoization in C++ (or Python)

エレガントなメモ化のやり方

 

同僚から教えてもらったテクニックを忘れそうになったのでメモ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <cstdio>
 
int memo[100][100];
 
int main() {
  memset(memo, -1, sizeof memo);
  // call f with parameters
  f(???, ???)
}
 
int f(int x, int y) {
  int& res = memo[x][y];
  if (res < 0) {
    // do the work when the value has not been calculated
    res = ???
  }
  return res;
}

適当なn次配列をメモ化の領域として使い、1のビット(-1)で初期化するところまでは一般的なやり方。

ポイントは、実際にメモ化したデータを使う部分。
はじめに配列の要素の参照を取り、初期状態でない場合にのみその値を更新する。
いずれのケースでも最後にその参照を返す。

これで処理の流れがシンプルになるし、メモの更新し忘れを防ぐこともできる。

同様に、Python で値が None で初期化されているならこんな感じ。

1
2
3
4
5
def f():
    if cache is None:
        # do the work
        cache = ???
    return cache