Test By Number
Definition:
Production code is tested consistently by rote, inadvertently suppressing creativity in the design of both the tests and their subjects.
Code Example:
# Test
class TestByNumber < SmellTest
def setup
@repo = Repo.new
@subject = AddressController.new(@repo)
super
end
def test_create
user = @repo.save(OpenStruct.new(name: 'Jane', addresses: []))
address_params = OpenStruct.new(street: 'some street')
@subject.create(user, address_params)
address = @repo.find(address_params.id)
assert_equal "some street", address.street
assert_equal address, user.addresses[0]
end
def test_read
address = @repo.save(OpenStruct.new(street: 'a street'))
user = @repo.save(OpenStruct.new(name: 'Joe', addresses: [address]))
result = @subject.read(user, address.id)
assert_equal address, result
end
def test_update
address = @repo.save(OpenStruct.new(street: 'no street', zip: '12345'))
user = @repo.save(OpenStruct.new(name: 'Jill', addresses: [address]))
@subject.update(user, {
id: address.id,
street: 'the street'
})
address = @repo.find(address.id)
assert_equal "the street", address.street
assert_equal "12345", address.zip
end
def test_destroy
address = @repo.save(OpenStruct.new(street: 'foo street'))
user = @repo.save(OpenStruct.new(name: 'Gene', addresses: [address]))
@subject.destroy(user, address.id)
assert_equal nil, @repo.find(address.id)
assert_equal 0, user.addresses.length
end
# Fake production implementations to simplify example test of subject
class Repo
def initialize
@items = {}
@next_id = 1
end
def save(item)
item.id = item.id || @next_id += 1
@items[item.id] = item
return item
end
def find(item_id)
@items[item_id]
end
def destroy(item_id)
@items.delete(item_id)
end
end
end
References:
Quality attributes
- Code Example
- Cause and Effect
- Frequency
- Refactoring