GithubHelp home page GithubHelp logo

bdd-stack's Introduction

BDD で Stack を作る講習

目的

ジラフのエンジニアの基礎能力として BDD を全員が出来るようにしたい。

BDD の効用

  • 少なくとも正常系の spec があることが保証される。
  • cli で回すので一度の試行錯誤にかかる時間が短縮され、結果的に大きなアウトプットが出来るようになる。
  • API を先に考えなkれば spec は書けないので結果的にしっかり考えられた API になる。
  • 技術力++

事前準備

rspec を単体で使います。

$ gem install rspec

講習

No.0 空の class を作る

コマンド

$ mkdir {lib,spec}
$ touch lib/stack.rb spec/spec_helper.rb spec/stack_spec.rb

ファイル

# lib/stack.rb
class Stack
end
# spec/spec_helper.rb
require 'stack'
# spec/stack_spec.rb
require 'spec_helper'

RSpec.describe Stack do
end

実行する

 $ rspec spec/stack_spec.rb
No examples found.


Finished in 0.00042 seconds (files took 0.29251 seconds to load)
0 examples, 0 failures

No.1 Stack の仕様を考える

  1. push 出来る?
  2. pop 出来る?
  3. length を取得出来る?
  4. empty? かどうかを尋ねられる?

No.2 spec を書いて実行する

# spec/stack_spec.rb
require 'spec_helper'

RSpec.describe Stack do
  let(:stack) { Stack.new }

  describe "#push" do
    subject { stack.push 1 }
    it { expect(subject).to eq stack }
  end
end

実行する

$ rspec spec/stack_spec.rb
F

Failures:

  1) Stack#push
     Failure/Error: subject { stack.push 1 }

     NoMethodError:
       undefined method `push' for #<Stack:0x00007f8f3a8c5ea8>
     # ./spec/stack_spec.rb:7:in `block (3 levels) in <top (required)>'
     # ./spec/stack_spec.rb:8:in `block (3 levels) in <top (required)>'

Finished in 0.00303 seconds (files took 0.22636 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/stack_spec.rb:8 # Stack#push

No.3 Error を Failure にする

# lib/stack.rb
class Stack
  def push(value)
  end
end

実行する

 $ rspec spec/stack_spec.rb
F

Failures:

  1) Stack#push should eq #<Stack:0x00007fd42f158578>
     Failure/Error: it { expect(subject).to eq stack }

       expected: #<Stack:0x00007fd42f158578>
            got: nil

       (compared using ==)
     # ./spec/stack_spec.rb:8:in `block (3 levels) in <top (required)>'

Finished in 0.02387 seconds (files took 0.25895 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/stack_spec.rb:8 # Stack#push should eq #<Stack:0x00007fd42f158578>

No.4 実装する

# lib/stack.rb
class Stack
  def push(value)
    self
  end
end

実行する

 $ rspec spec/stack_spec.rb
.

Finished in 0.00217 seconds (files took 0.10744 seconds to load)
1 example, 0 failures

No.5 前提条件のある spec で Fake it

# spec/stack_spec.rb
...
  context "1 を push 済みの stack" do
    before { stack.push 1 }
    describe "length が 1" do
      subject { stack.length }
      it { expect(subject).to eq 1 }
    end
  end
...

実行する

$ rspec spec/stack_spec.rb
.F

Failures:

  1) Stack 1 を push 済みの stack length が 1
     Failure/Error: subject { stack.length }

     NoMethodError:
       undefined method `length' for #<Stack:0x00007fc82d8fe308>
     # ./spec/stack_spec.rb:14:in `block (4 levels) in <top (required)>'
     # ./spec/stack_spec.rb:15:in `block (4 levels) in <top (required)>'

Finished in 0.00295 seconds (files took 0.10604 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/stack_spec.rb:15 # Stack 1 を push 済みの stack length が 1

Error を Failure にする

# lib/stack.rb
...
  def length
  end
...

実行する

 $ rspec spec/stack_spec.rb
.F

Failures:

  1) Stack 1 を push 済みの stack length が 1 should eq 1
     Failure/Error: it { expect(subject).to eq 1 }

       expected: 1
            got: nil

       (compared using ==)
     # ./spec/stack_spec.rb:15:in `block (4 levels) in <top (required)>'

Finished in 0.01297 seconds (files took 0.10957 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/stack_spec.rb:15 # Stack 1 を push 済みの stack length が 1 should eq 1

Fake it(仮実装)

# lib/stack.rb
  def length
    1
  end

実行する

 $ rspec spec/stack_spec.rb
..

Finished in 0.00296 seconds (files took 0.108 seconds to load)
2 examples, 0 failures

No.6 前提条件を増やして実実装

# spec/stack_spec.rb
...
  context "1 と 5 を push 済みの stack" do
    before do
      stack.push 1
      stack.push 5
    end
    subject { stack.length }
    describe "length が 2" do
      it { expect(subject).to eq 2 }
    end
  end
...

実行する

 $ rspec spec/stack_spec.rb
..F

Failures:

  1) Stack 1 と 5 を push 済みの stack length が 2 should eq 2
     Failure/Error: it { expect(subject).to eq 2 }

       expected: 2
            got: 1

       (compared using ==)
     # ./spec/stack_spec.rb:26:in `block (4 levels) in <top (required)>'

Finished in 0.01281 seconds (files took 0.10742 seconds to load)
3 examples, 1 failure

Failed examples:

rspec ./spec/stack_spec.rb:26 # Stack 1 と 5 を push 済みの stack length が 2 should eq 2

Failure を Error にして実実装を行なう

# lib/stack.rb
class Stack
  def initialize
    @buffer = []
  end

  def push(value)
    @buffer.push(value)
    self
  end

  def length
    @buffer.length
  end
end

実行する

 $ rspec spec/stack_spec.rb
...

Finished in 0.00312 seconds (files took 0.10855 seconds to load)
3 examples, 0 failures

No.7 spec の書き方がまずかったのでリファクタリングする

# spec/stack_spec.rb
require 'spec_helper'

RSpec.describe Stack do
  let(:stack) { Stack.new }

  describe "#push" do
    subject { stack.push 1 }
    it { expect(subject).to eq stack }
  end

  describe "#length" do
    subject { stack.length }
    context "1 を push 済みの stack" do
      before { stack.push 1 }
      it { expect(subject).to eq 1 }
    end
    context "1 と 5 を push 済みの stack" do
      before do
        stack.push 1
        stack.push 5
      end
      it { expect(subject).to eq 2 }
    end
  end
end

実行する

 $ rspec spec/stack_spec.rb
...

Finished in 0.00336 seconds (files took 0.11113 seconds to load)
3 examples, 0 failures

課題

bdd-stack's People

Contributors

h7kayama avatar yalab avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.