Article:
RSpec animals
761
ngocdaothanh.myopenid.com 149Updated about 1 year ago |
Animals có đáng RSpec hay không?
Sau khi học OOP với 4 đặc thù của lập trình hướng đối tượng và RSpec với Bắt đầu với RSpec, ta thực hành viết spec cho các class đó xem sao.
Cấu trúc thư mục
Tạo cấu trúc thư mục như sau:
animals_with_rspec
+animal
+animal.rb
+cat.rb
+dog.rb
+zoo.rb
+spec
+animals_spec.rb
+zoo_spec.rb
Animals
Nội dung các tập tin trong thư mục animal có thay đổi chút ít so với bài 4 đặc thù của lập trìn hướng đối tượng.
animal.rb
class Animal
attr_reader :name
def initialize(name)
@name = name
end
def say_hello
puts "I am animal, my name is #{@name}"
end
end
cat.rb
require File.expand_path(File.dirname(__FILE__) + '/animal')
class Cat < Animal
def say_hello
puts "Meow, my name is #{@name}"
end
end
dog.rb
require File.expand_path(File.dirname(__FILE__) + '/animal')
class Dog < Animal
def say_hello
puts "Woof woof, my name is #{@name}"
end
end
zoo.rb
class Zoo
attr_reader :animals
def initialize
@animals = []
end
def add(animal)
@animals << animal
end
def remove(animal)
@animals.delete(animal)
end
def say_hello
@animals.each { |a| a.say_hello }
end
end
Spec
Đúng ra phải viết spec trước, định nghĩa WHAT xong rồi mới sang bước HOW là viết chương trình. Làm ngược thế này thì đúng là:
Sinh con rồi mới sinh cha
Sinh cháu giữ nhà rồi mới sinh ông
animals_spec.rb
Dir.glob(File.dirname(__FILE__) + '/../animal/*.rb') do |file|
require file
end
[Animal, Cat, Dog].each do |klass|
describe klass do
it 'should be initialized with a name' do
name = 'Bush'
animal = klass.new(name)
animal.should_not be_nil
animal.name.should eql(name)
end
it 'should be able to say hello' do
animal = klass.new('Bush')
animal.say_hello
end
end
end
zoo_spec.rb
Dir.glob(File.dirname(__FILE__) + '/../animal/*.rb') do |file|
require file
end
describe Zoo do
before(:each) do
@zoo = Zoo.new
end
it 'should have 0 animal after created' do
@zoo.animals.size.should eql(0)
end
it 'should have 1 more animal when one is added and 1 less animal when one is removed' do
cat = Cat.new('Bush')
@zoo.add(cat)
@zoo.animals.size.should eql(1)
@zoo.remove(cat)
@zoo.animals.size.should eql(0)
end
it 'should let all animals say hello' do
@zoo.add(Cat.new('Bush1'))
@zoo.add(Dog.new('Bush2'))
@zoo.say_hello
end
end
Chạy spec
Sau khi cài RSpec (gem install rspec), trên máy có thêm lệnh spec. Để chạy test spec, cú pháp căn bản: spec <tên tập tin>. Khi chạy lệnh này, các tập tin của thư viện RSpec sẽ được require tự động, ta không cần tự require trong các tập tin _spec.rb.
Từ thư mục animals_with_rspec: spec spec/animals_spec.rb
.I am animal, my name is Bush
..Meow, my name is Bush
..Woof woof, my name is Bush
.
Finished in 0.032561 seconds
6 examples, 0 failures
Để xuất ra đẹp hơn, dùng thử tham số --format specdoc
Animal
- should be initialized with a name
I am animal, my name is Bush
- should be able to say hello
Cat
- should be initialized with a name
Meow, my name is Bush
- should be able to say hello
Dog
- should be initialized with a name
Woof woof, my name is Bush
- should be able to say hello
Finished in 0.020232 seconds
6 examples, 0 failures
Để biết các tham số khác (ví dụ để xuất ra HTML rất đẹp, có thể in ra thành tài liệu báo cáo sếp hoặc khách hàng): spec -h.
Dùng wildcard để chạy tất cả test trong thư mục: spec spec/* --format specdoc
Animal
- should be initialized with a name
I am animal, my name is Bush
- should be able to say hello
Cat
- should be initialized with a name
Meow, my name is Bush
- should be able to say hello
Dog
- should be initialized with a name
Woof woof, my name is Bush
- should be able to say hello
Zoo
- should have 0 animal after created
- should have 1 more animal when one is added and 1 less animal when one is removed
Meow, my name is Bush1
Woof woof, my name is Bush2
- should let all animals say hello
Finished in 0.024873 seconds
9 examples, 0 failures
149
