我正在构建一个投资工具,并希望确保它计算正确的到期金额。
以下是一些源代码:
def maturity_amount
if cumulative
amount = initial_deposit * (1 + (rate_of_interest)/4 ) ** (term * 4)
amount.round
else
initial_deposit
end
end
所以我写了一个这样的测试:
it "can calculate interest earned" do
investment = FactoryGirl.build(:investment, initial_deposit: 250000, rate_of_interest: 9.5, cumulative: true)
expect(investment.maturity_amount).to eq(331335)
end
你在这里看到我将结果硬编码到测试中。这会使测试变得脆弱吗?此外,我似乎无法在不更新最终结果的情况下轻松改变我给测试的输入。
那么有更好的方法来编写测试并且仍然对进行正确的计算有信心吗?我应该嘲笑吗?或者我不应该首先编写这样的测试?如果是这样,为什么?
答案 0 :(得分:1)
由于您的到期日金额取决于某些条件,我认为它需要更多的测试。这是我可能会如何规范你的方法的行为(并稍微重构你的类)
我假设你的班级名为Investment
:
class Investment
def maturity_amount
if cumulative
# kept the `.round` out here in case you had other functions
# that may take the `ceil` or `floor` etc of `interest_earned`
interest_earned.round
else
initial_deposit
end
end
# Refactor out the formula into its own method so it can
# be tested in isolation
def interest_earned
initial_deposit * (1 + (rate_of_interest)/4 ) ** (term * 4)
end
end
describe Investment do
let(:investment) { described_class.new }
describe '#maturity_amount' do
let(:maturity_amount) { investment.maturity_amount }
context 'when amount is cumulative' do
before do
allow(investment).to receive(:cumulative).and_return(true)
allow(investment).to receive(:interest_earned).and_return(9999.8)
end
it 'returns the rounded value of the cumulative amount' do
expect(maturity_amount).to eq(10000)
end
end
context 'when amount is not cumulative' do
before do
allow(investment).to receive(:cumulative).and_return(false)
allow(investment).to receive(:initial_deposit).and_return(10000)
end
it 'returns the initial deposit' do
expect(maturity_amount).to eq(10000)
end
end
end
describe '#interest_earned' do
let(:interest_earned) { investment.interest_earned }
# you may have various circumstances/edge cases where you would like to
# test that the interest earned calculates what you would expect, and I
# would put them in different `context` blocks, but for simplicity's sake
# I'll just use one simple case here
before do
# using the Factory values from your question...
allow(investment).to receive(:initial_deposit).and_return(250000)
allow(investment).to receive(:rate_of_interest).and_return(9.5)
# not sure of your default term value would be, so just use 1
allow(investment).to receive(:term).and_return(1)
end
it 'calculates the interest earned' do
# something seems a bit strange here given this passing test...
# I assume there are other values that contribute to this calculation
# that I'm missing
expect(interest_earned).to eq(32436584.47265625)
end
end
end
答案 1 :(得分:0)
看起来不错!测试远非脆弱。如果您更改输入或算法,测试将只会失败,这正是它应该失败的条件。测试不应该有任何逻辑或元编程。
如果您没有根据输入做不同的事情,则无需使用不同的输入编写许多测试。这将增加测试套件的维护负担,而不会增加任何值。
简单就是更好。