Behavior-Driven Development

내게 객체 기반 프로그래밍 (Object-Oriented Programming)를 한마디로 축약하라면, 행동(Behavior)을 기준으로 도메인을 나누는(decomposition)하는 프로그래밍 방식이라고 정의할 것이다. 다시 말해, 객체(Object)는 잘 정의된 행동(Behavior)을 대표해야한다는 것이다. 행동(Behavior)이 아니라 자료(Data)를 기준으로 디자인하면, 구조화 프로그래밍(Structured programming)의 수동적인 자료구조와 그것을 조작하는 함수들의 집합이 탄생할 뿐이다. 설령 그것이 클래스라는 프로그래밍 언어 상의 장치를 사용한다고 하더라도 객체 기반 프로그래밍이라고 부를 수는 없다. (이러한 밈(meme)에 대해서는 Object Thinking이라는 책을 참고하라.)

Behavior-Driven Development라는 말을 강문식 군에게 처음 들었을 때는 이러한 객체 기반 프로그래밍의 생각을 대변하는 일반적인 개념을 가진 말이라고 추측했는데, 알고보니 정체는 그 개념을 TDD에 적용한 좁은 의미의 것이었다. Dave Astels 자신이 정의한대로 Behavior-Driven Specification 같은 용어를 썼으면 좋았을텐데 하는 생각이 든다.

설령 그렇다고 하더라도, 행동을 기준으로 하는 디자인이 맨 먼저 테스트에 적용되는 것은 상당히 훌륭한 개념이라고 생각한다. TDD를 통해서 얻을 수 있는 이점인 재사용과 테스트가 쉬운 (Reusable and Testable) 프로그램을 만드는데 있어서 객체 기반 프로그래밍의 기본 개념인 행동(Behavior)을 기준으로 한 디자인까지 할 수 있다면, 더할 나위 없이 좋을 것이다. 다만, 그것이 테스트 또는 스펙에만 머무르지 않고 실제 행동(Behavior)을 나타내는 디자인에까지 적용되어야 하겠지만 말이다.

아래는 Dave AstelsBDD에 대한 Google TechTalks 강연 내용 요약.

Unit vs. Behavior

unit: isolated focus like class, method
behavior: little fine-grained focused picses of behavior

unit should replaced by behavior
test should replaced by specification
assertion should replaced by expectation

rSpec

xunit should replaced by rSpec
assert_equal(expected, actual)->actual.should.equal expected

The Expectation API

  • equality
    • e.g. should.equal/sould.not.equal
  • counts
    • should.have(5).items
    • should.have.at.least(5).items
    • should.have.at.most(5).items
  • arbitrary block
    • should.satisfy { |obj| … }
    • should.not.satisfy { |obj| … }
  • pattern matching
    • should.match
  • arbitrary predicate
    • should.predicate (predicate? is defined on the target)
  • forced failure
    • violated(message)
  • exception
    • should.raise <exception>
  • direct class
    • should.be.an.instance.of C
  • ancestor class
    • should.be.a.kind.of C
  • interface
    • should.response.to :message

The Mocking API

just like jMock

  • creating a mock
    • m = mock(“mock name”)
  • expecting a method
    • should_receive(:name)
  • counts
    • never/once/twice/at_least_once/any_number_of_times
  • Arguments
    • with_no_args
    • with_any_args
    • with(arg1, arg2, …)
  • Return values
    • and_returns(value)
    • and_returns_consecutively([…])
  • Provide a Block
    • should_receive(:name) {
    • |arg1, args2, …|

Why Ruby?

  • Dynamic
  • Productive
  • Fun

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.