名古屋アジャイル勉強会のTDDワークショップ
名古屋アジャイル勉強会でテスト駆動開発の体験ワークショップを行いました。
僕はスタッフとして、テスト駆動開発の簡単な解説をしたのと、ペアプロでC言語でstackを実装するのをやりました。
テスト駆動開発の説明は、t-wadaさんの資料(プレゼンや動画)がwebで見られるので、わざわざ作るまでもない気もしましたが、資料借用して済ませるのもまずいと思い、簡単なものを作りました。テスト駆動開発とは、今から書こうとする数行のコードの意図を、まずテストという形で表明する、というやり方のプログラミング技法です、と説明しました。テストの価値、品質との関係、などは、僕からは説明せずにみんなで考えてみましょう、みたいな話にしちゃいました。
そのあとorphiriaさんとペアで書いたコードは以下の通りです。
makefile
all: gcc -Wall -g -c *.c g++ -Wall -g -c *.cpp g++ -Wall -o a.out *.o ./a.out
こりゃいちじるしくなんちゃってですね。
unittest.h
このヘルパマクロのヘッダファイルだけは、事前に用意しておきました。これは僕はよく使っているものです。
#ifndef __UNITTEST_H__ #define __UNITTEST_H__ #include <stdio.h> #define RUN_TEST(test) \ do { \ printf(#test); fflush(stdout); test(); printf("\tOK\n"); \ } while(0) #endif
main.cpp
#include "unittest.h" #include <iostream> #include "string.h" using namespace std; void test_stack() { struct stack a_stack; init(&a_stack); assert(0 == stack_size(&a_stack)); stack_push(&a_stack, 100); assert(1 == stack_size(&a_stack)); assert(100 == stack_pop(&a_stack)); assert(0 == stack_size(&a_stack)); stack_push(&a_stack, 200); assert(1 == stack_size(&a_stack)); assert(200 == stack_pop(&a_stack)); assert(0 == stack_size(&a_stack)); stack_push(&a_stack, 300); assert(1 == stack_size(&a_stack)); stack_push(&a_stack, 400); assert(2 == stack_size(&a_stack)); assert(400 == stack_pop(&a_stack)); assert(1 == stack_size(&a_stack)); assert(300 == stack_pop(&a_stack)); assert(0 == stack_size(&a_stack)); } int main(int argc, const char * argv[]) { RUN_TEST(test_stack); cout << "OK" << endl; return 0; }
stack.h
#ifndef STACK_H #define STACK_H #include <stdlib.h> struct stack { size_t size; int value[2]; }; #endif
stack.c
#include "stack.h" #include "string.h" size_t stack_size(struct stack * a_stack) { return a_stack->size; } void stack_push(struct stack * a_stack, int n) { a_stack->value[a_stack->size] = n; ++(a_stack->size); } int stack_pop(struct stack * a_stack) { --(a_stack->size); return a_stack->value[a_stack->size]; } void init(struct stack * a_stack) { memset(a_stack, 0, sizeof(struct stack)); }
ユニットテスト実行のフレームワーク的なものは、unittest.hに定義したヘルパマクロだけです。assertは標準ライブラリのマクロを使っています。なにかフレームワークを使えばもっと便利ですが、この程度のものでもできるよ、という例ということで。
C言語での実装ですが、テストはC++にしています。上記例ではCでもよかったかしらと思いますが、もうちょっと込み入ったテストになってきたら、RAIIとか使えるC++の方が便利なので。
stack.cの実装は、かなりノーガード戦法な感じですが、とりあえず、テスト駆動でここまで導出できました、ということでご理解ください。用法間違えてエラーになるテストを作って、改善していくのは、今回はできませんでしたけど、時間があったらやるところです。capacityが2固定というのもありえないので、当然見直すところですね。