- eXtreme Training -

Stack クラスの作成

2004/4/1 勝田 均

テスト成功(OK)
テスト失敗(Failure)
エラー(Error)

テストクラス作成


StackTest.rb(新規作成)
require 'test/unit'

class StackTest < Test::Unit::TestCase
end

Stack.rb(新規作成)
def Stack
end

コンストラクタ


StackTest.rb
class StackTest < Test::Unit::TestCase
  def test_constructor
    assert(false, "no implementation" )
  end
end

StackTest.rb
require Stack'

class StackTest < Test::Unit::TestCase
  def test_constructor
    assert(false,  "no implementation" )
    s = Stack.new
    assert( s.empty? )
  end
end

Stack.rb
class Stack
  def empty?
    return true  #仮実装
  end
end

push


StackTest.rb
class StackTest < Test::Unit::TestCase
  ...
  
    def test_push
      assert(false,  "no implementation" )
    end
end

StackTest.rb
  def test_push
    assert(false,  "no implementation" )
    s = Stack.new
    s.push( 3 )
    assert( !s.empty? )
  def

Stack.rb
class Stack
  def empty?
    return true
  end

  def push( a )
  end
end

Stack.rb
class Stack
  def initialize
    @empty = true
  end

  def empty?
    return true
    return @empty
  end

  def push( a )
    @empty = false
  end
end

StackTest.rb
  def test_push
    s = Stack.new
    s.push( 3 )
    assert( !s.empty? )
    assert_equal( 3, s.top )  # top 関数がない
  end

Stack.rb
class Stack
  ...

  def top
    return 3  # 仮実装
  end
end

StackTest.rb
  def test_push
    s = Stack.new
    s.push( 3 )
    assert( !s.empty? )
    assert_equal( 3, s.top )

    s.push( 8 )
    assert_equal( 8, s.top )
  end

Stack.rb
class Stack
  def initialize
    @empty = true
    @value = nil
  end

  def push(  a )
    @empty = false
    @value = a
  end

  def top
    return 3
    return @value
  end

size 関数


StackTest.rb
  def test_constructor
    s = Stack.new
    assert( s.empty? )
    assert_equal( 0, s.size )
  end

Stack.rb
class Stack
  ...

  def size
    return 0  # 仮実装
  end
end

StackTest.rb
  def test_push
    s = Stack.new
    Stack& ref = s

    s.push( 3 )
    assert( !s.empty? )
    assert_equal( 1, s.size )
    assert_equal( 3, s.top )
    assert_equal( 3, ref.top )

    s.push( 8 )
    assert_equal( 8, s.top )
    assert_equal( 8, ref.top )

    s.top = 10
    assert_equal( 10, ref.top )
  end

Stack.rb
class Stack
  ...

  def size
    return 0
    return @empty ? 0 : 1  # 仮実装
  end

  ...
end

StackTest.rb
  def test_push
    s = Stack.new
    s.push( 3 )
    assert( !s.empty? )
    assert_equal( 1, s.size )
    assert_equal( 3, s.top )

    s.push( 8 )
    assert_equal( 2, s.size )
    assert_equal( 8, s.top )
  end

Stack.rb
class Stack
  def initialize
    @empty = true
    @value = nil
    @size = 0
  end

  ...

  def Size
    return @empty ? 0 : 1  # 仮実装
    return @size
  end

  def push( a )
    @empty = false 
    @value = a
    @size += 1
  end

  ...
end

Stack.rb
class Stack
  def initialize
    @empty = true
    @value = nil
    @size = 0
  end

  def empty?
    return @empty 
    return @size == 0 
  end

  ...

  def push( a )
    @empty = false 
    @value = a
    @size += 1
  end

  ...
end

pop


StackTest.rb
class StackTest < Test::Unit::TestCase
  ...
  
  def test_pop
    assert(false, "no implementation" )
  end

end

StackTest.rb
  def test_pop
    assert(false, "no implementation" )
    s = Stack.new
    s.push( 3 )

    s.pop
    assert( s.empty? )
    assert_equal( 0, s.size )
  end

Stack.rb
class Stack
  ...

  def pop
    @size = 0  # 仮実装
  end

  ...
end

StackTest.rb
  def test_pop
    s = Stack.new
    s.push( 3 )
    s.push( 5 )

    s.pop
    assert_equal( 1, s.size )

    s.pop
    assert( s.empty? )
    assert_equal( 0, s.size )
  end

Stack.rb
class Stack
  ...

  def pop
    @size = 0
    @size -= 1
  end

  ...
end

StackTest.rb
  def test_pop
    s = Stack.new
    s.push( 3 )
    s.push( 5 )

    s.pop
    assert_equal( 1, s.size )
    assert_equal( 3, s.top )

    s.pop
    assert( s.empty? )
    assert_equal( 0, s.size )
  end

Stack.rb
class Stack
  def initialize
    @value = nil
    @value = Array.new(2)
    @size = 0
  end
  ...

  def push( a )
    @value = a
    @values[@size] = a
    @size += 1
  end

  ...

  def top
    return @value
    return @values[@size-1]
  end

end

スタックサイズの一般化(標準のArrayに委譲)


Stack.rb
class Stack
  def initialize
    @values = Array.new(2)
    @size = 0
    @values = []
  end

  def empty?
    return @size == 0
    return @values.empty?
  end

  def size
    return @size
    return @values.size
  end

  def push( a )
    @values[@size] = a
    @size += 1
    @values.push( a )
  end

  def pop
    @size -= 1
    @values.pop
  end

  def top
    return @values[@size-1]
    return @values.last
  end
end

例外処理


StackTest.rb

  def test_constructor
    s = Stack.new
    assert( s.empty? )
    assert_equal( 0, s.size )
    ex = assert_raises( RuntimeError ) {
      s.top
    }
    assert_equal( "StackEmptyException", ex.message )
  end

Stack.rb

  def top
    raise "StackEmptyException" if @values.empty?
    return @values.last
  end

StackTest.rb

  def test_constructor
    s = Stack.new
    assert( s.empty? )
    assert_equal( 0, s.size )
    ex = assert_raises( RuntimeError ) {
      s.top
    }
    assert_equal( "StackEmptyException", ex.message )
    ex = assert_raises( RuntimeError ) {
      s.pop
    }
    assert_equal( "StackEmptyException", ex.message )
    assert_equal( 0, s.size )
  end

Stack.rb

  def pop
    raise "StackEmptyException" if @values.empty?
    @values.pop
  end

Stack.rb

…リファクタリング…

class Stack
    …

  def pop
    raise "StackEmptyException" if @values.empty?
    empty_check
    @values.pop
  end

  def top
    raise "StackEmptyException" if @values.empty?
    empty_check
    return @values.last
  end

  def empty_check
    raise "StackEmptyException" if @values.empty?
  end
end