shizuto on languages

言語好きの組込みプログラマが言語から言語じゃないものまで語ります。On y va!

「簡単なものこそBDDで!」 〜 LTSpiral #2 で発表してきました。

先週、関西IT系若手勉強会 LTSpiral (
LTSpiral | Google グループ
) 第二回に参加してきました。1回目は社会人3年目まで(学生含む)が対象でしたが、今回は社会人6年目までに拡大され、パワーアップ!(?) IT系といっても業界はWebからインフラ、組込み(僕だけ?)まで、立場もエンジニアだけではないし、いろんな人が集まってわいわい話ができるのが面白いです。

僕も2枠(20分)いただいて、「BDDやろうぜ!」とお話してきました。

使ったソースコードはこちら。とりあえず完成形の sample3 だけ載せておきます。

sample3_spec.rb (スペックのほう)

# -*- encoding: utf-8 -*-

require 'sample3'

describe Animal do
    describe '#new' do
        it "should not be raised" do
            lambda{ Animal.new }.should raise_error
        end
    end
end

describe Bear do
    before :each do
        @janos = Bear.new("Janos")
    end

    describe '#name' do
        it "should return its name" do
            @janos.name.should == "Janos"
        end
    end

    describe '#kind' do
        it "should return its kind" do
            @janos.kind.should == "bear"
        end
    end
end

describe Penguin do
    before :each do
        @penguin = Penguin.new("Brik")
    end

    describe '#name' do
        it "should return its name" do
            @penguin.name.should == "Brik"
        end
    end

    describe '#kind' do
        it "should return its kind" do
            @penguin.kind.should == "penguin"
        end
    end
end


describe Cage do
    before :each do
        @cage = Cage.new("New Cage")

        @penguin1 = Penguin.new("Penpen")
        @penguin2 = Penguin.new("Liebe")
        @bear1 = Bear.new("Wink")
        @bear2 = Bear.new("White")

        @cage.add_member(@penguin1)
        @cage.add_member(@bear1)

        @empty_cage = Cage.new("Empty Cage")
    end

    describe '#new' do
        it "should create an empty cage with given name" do
            newcage = Cage.new("Green Yard")
            newcage.name.should == "Green Yard"
            newcage.members.should be_empty
        end

        it "should give default name if no name was given" do
            newcage = Cage.new
            newcage.name.should == "No Name"
        end
    end

    describe '#name' do
        it "should return its name" do
            @cage.name.should == "New Cage"
        end
    end

    describe '#add_member(animal)' do
        it "should add the animal into the cage" do
            @cage.add_member(@bear2)
            @cage.should have_a(@bear2)
        end

        it "should not accept non-animal" do
            lambda{ @cage.add_member(123) }.should raise_error
        end
    end

    describe '#members' do
        it "should return the list of members" do
            @cage.members.should have(2).items
            @empty_cage.members.should be_empty
        end
    end

    describe '#num_of_members' do
        it "should return the number of members" do
            @cage.num_of_members.should == 2
            @empty_cage.num_of_members.should == 0
        end
    end

    describe '#introduce_by_name' do
        it "should call all names" do
            @cage.introduce_by_name.should include("Penpen")
            @cage.introduce_by_name.should include("Wink")
        end

        it "should tell it if there is no animals" do
            @empty_cage.introduce_by_name.should == "There is no animal"
        end
    end

    describe '#introduce_by_kind' do
        it "should classify animals and count" do
            @cage.add_member(@bear2)
            @cage.introduce_by_kind.should include("1 penguin")
            @cage.introduce_by_kind.should include("2 bears")
        end

        it "should tell it if there is no animals" do
            @empty_cage.introduce_by_kind.should == "There is no animal"
        end
    end
end

sample3.rb (こっちが本体)

# -*- encoding: utf-8 -*-

class Animal
    def initialize(name)
        raise "Animal cannot be used without inherit"
    end

    attr_reader :name
end

class Bear < Animal
    def initialize(name)
        @name = name
    end
    
    def kind
        "bear"
    end
end

class Penguin < Animal
    def initialize(name)
        @name = name
    end

    def kind
        "penguin"
    end
end


class Cage
    def initialize(name="No Name")
        @name = name
        @members = []
    end

    attr_reader :name, :members

    def add_member(animal)
        if animal.is_a? Animal
            @members << animal
        else
            raise "#{animal} is not an animal"
        end
    end

    def has_a?(animal)
        members.include?(animal)
    end

    def num_of_members
        members.size
    end

    def introduce_by_name
        return "There is no animal" if num_of_members == 0

        "There are " + members.map{|x| x.name}.join(", ")
    end

    def introduce_by_kind
        return "There is no animal" if num_of_members == 0

        # classify by kind
        count_hash = Hash.new(0)
        members.each do |x|
            count_hash[x.kind] += 1
        end

        ary = []
        count_hash.each do |kind, num|
            ary << "#{num} #{kind}s" # now use plural if one
        end

        "There are " + ary.join(", ")
    end
end