Best Value: candidate-priced fills, key copy, detail total
This commit is contained in:
@@ -82,18 +82,84 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
XCTAssertEqual(FuelSavingsFormat.distance(1, unit: .miles), DistanceUnit.miles.format(1.609344))
|
||||
}
|
||||
|
||||
// MARK: - 2/4. The three stations from the brief
|
||||
// MARK: - 2. Candidate-priced fill-up
|
||||
|
||||
func testPoundsFillUsesCandidatePriceForLitresAndGrossSaving() throws {
|
||||
let result = try FuelSavingsCalculator.calculate(
|
||||
mpg: 30,
|
||||
amount: FuelSavingsFillAmount(value: 60, unit: .pounds),
|
||||
baselinePricePencePerLitre: 171.9,
|
||||
candidatePricePencePerLitre: 169.9,
|
||||
baselineJourneyMiles: 0.879,
|
||||
candidateJourneyMiles: 8.306
|
||||
)
|
||||
|
||||
XCTAssertEqual(result.fillLitres, 60 / 1.699, accuracy: 1e-9)
|
||||
XCTAssertEqual(result.grossSavingGBP, (60 / 1.699) * 0.02, accuracy: 1e-9)
|
||||
XCTAssertEqual(FuelSavingsFormat.money(result.grossSavingGBP), "£0.71")
|
||||
XCTAssertEqual(result.extraFuelLitres, 1.1254603476666667, accuracy: 1e-9)
|
||||
XCTAssertEqual(result.extraDrivingCostGBP, 1.9121571306856667, accuracy: 1e-9)
|
||||
XCTAssertEqual(result.netSavingGBP, -1.2058593084372853, accuracy: 1e-9)
|
||||
XCTAssertEqual(result.headline(), "Costs £1.21 more")
|
||||
}
|
||||
|
||||
func testPoundsExamplesScaleFromThirtyToOneHundredPounds() throws {
|
||||
for (budget, expectedLitres, expectedGross) in [
|
||||
(30.0, 17.657445556209535, 0.3531489111241907),
|
||||
(60.0, 35.31489111241907, 0.7062978222483814),
|
||||
(100.0, 58.85815185403179, 1.1771630370806357)
|
||||
] {
|
||||
let result = try FuelSavingsCalculator.calculate(
|
||||
mpg: 30,
|
||||
amount: FuelSavingsFillAmount(value: budget, unit: .pounds),
|
||||
baselinePricePencePerLitre: 171.9,
|
||||
candidatePricePencePerLitre: 169.9,
|
||||
baselineJourneyMiles: 0,
|
||||
candidateJourneyMiles: 0
|
||||
)
|
||||
XCTAssertEqual(result.fillLitres, expectedLitres, accuracy: 1e-8)
|
||||
XCTAssertEqual(result.grossSavingGBP, expectedGross, accuracy: 1e-8)
|
||||
}
|
||||
}
|
||||
|
||||
func testCandidatePriceControlsLitresWhileBaselinePriceOnlyChangesSaving() throws {
|
||||
let amount = FuelSavingsFillAmount(value: 60, unit: .pounds)
|
||||
let first = try FuelSavingsCalculator.calculate(
|
||||
mpg: 30, amount: amount,
|
||||
baselinePricePencePerLitre: 171.9,
|
||||
candidatePricePencePerLitre: 169.9,
|
||||
baselineJourneyMiles: 0, candidateJourneyMiles: 0
|
||||
)
|
||||
let differentBaseline = try FuelSavingsCalculator.calculate(
|
||||
mpg: 30, amount: amount,
|
||||
baselinePricePencePerLitre: 179.9,
|
||||
candidatePricePencePerLitre: 169.9,
|
||||
baselineJourneyMiles: 0, candidateJourneyMiles: 0
|
||||
)
|
||||
let differentCandidate = try FuelSavingsCalculator.calculate(
|
||||
mpg: 30, amount: amount,
|
||||
baselinePricePencePerLitre: 179.9,
|
||||
candidatePricePencePerLitre: 159.9,
|
||||
baselineJourneyMiles: 0, candidateJourneyMiles: 0
|
||||
)
|
||||
|
||||
XCTAssertEqual(first.fillLitres, differentBaseline.fillLitres, accuracy: 1e-12)
|
||||
XCTAssertNotEqual(first.grossSavingGBP, differentBaseline.grossSavingGBP)
|
||||
XCTAssertNotEqual(differentBaseline.fillLitres, differentCandidate.fillLitres)
|
||||
}
|
||||
|
||||
// MARK: - 3/5. The three stations from the brief
|
||||
|
||||
func testBriefCaseTescoBradfordIsMarginallyWorseOff() throws {
|
||||
let result = try briefResult(candidatePrice: 170.9, extraMiles: 2.0)
|
||||
|
||||
XCTAssertEqual(result.fillLitres, 34.904014, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.grossSavingGBP, 0.349040, accuracy: 1e-6, "1p/litre cheaper on a 34.90 L fill")
|
||||
XCTAssertEqual(result.fillLitres, 35.108250, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.grossSavingGBP, 0.351083, accuracy: 1e-6, "£60 buys 35.11 L at the candidate price")
|
||||
XCTAssertEqual(result.extraDistanceMiles, 2.0, accuracy: 1e-9)
|
||||
XCTAssertEqual(result.extraDrivingCostGBP, 0.517951, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.netSavingGBP, -0.168911, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.netSavingGBP, -0.166869, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.status, .notWorthTheDrive)
|
||||
XCTAssertEqual(result.headline(), "£0.17 worse off after travel")
|
||||
XCTAssertEqual(result.headline(), "Costs £0.17 more")
|
||||
}
|
||||
|
||||
/// The brief recorded "£0.18 worse off" for this row against a displayed
|
||||
@@ -104,9 +170,9 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
/// is entirely the rounding of the distance, not of the money.
|
||||
func testTheReportedEighteenPenceIsRoundedExtraDistanceNotARoundingBug() throws {
|
||||
XCTAssertEqual(try briefResult(candidatePrice: 170.9, extraMiles: 2.00).headline(),
|
||||
"£0.17 worse off after travel")
|
||||
"Costs £0.17 more")
|
||||
XCTAssertEqual(try briefResult(candidatePrice: 170.9, extraMiles: 2.05).headline(),
|
||||
"£0.18 worse off after travel")
|
||||
"Costs £0.18 more")
|
||||
|
||||
// 2.05 mi shows as "2.0 mi" at one decimal place — the same caption.
|
||||
XCTAssertEqual(FuelSavingsFormat.extraTravelLabel(extraDistanceMiles: 2.05, unit: .miles),
|
||||
@@ -118,13 +184,13 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
func testBriefCaseMFGHareAndHoundsIsWorseOff() throws {
|
||||
let result = try briefResult(candidatePrice: 172.9, extraMiles: 2.8)
|
||||
|
||||
XCTAssertEqual(result.fillLitres, 34.904014, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.grossSavingGBP, -0.349040, accuracy: 1e-6, "1p/litre dearer costs 34.90 L × 1p")
|
||||
XCTAssertEqual(result.fillLitres, 34.702140, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.grossSavingGBP, -0.347021, accuracy: 1e-6, "£60 buys 34.70 L at the candidate price")
|
||||
XCTAssertEqual(result.extraDistanceMiles, 2.8, accuracy: 1e-9)
|
||||
XCTAssertEqual(result.extraDrivingCostGBP, 0.733618, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.netSavingGBP, -1.082658, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.netSavingGBP, -1.080639, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.status, .notWorthTheDrive)
|
||||
XCTAssertEqual(result.headline(), "£1.08 worse off after travel")
|
||||
XCTAssertEqual(result.headline(), "Costs £1.08 more")
|
||||
}
|
||||
|
||||
func testBriefCasePGGNapoleonSamePumpPriceIsTravelCostOnly() throws {
|
||||
@@ -135,7 +201,7 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
XCTAssertEqual(result.netSavingGBP, -0.729375, accuracy: 1e-6,
|
||||
"with no price difference the whole result is the extra driving")
|
||||
XCTAssertEqual(result.status, .notWorthTheDrive)
|
||||
XCTAssertEqual(result.headline(), "£0.73 worse off after travel")
|
||||
XCTAssertEqual(result.headline(), "Costs £0.73 more")
|
||||
}
|
||||
|
||||
// MARK: - 5/6. Classification, tolerance and rounding
|
||||
@@ -150,15 +216,15 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testSmallSavingInsideTheToleranceIsBreakEvenNotPennies() throws {
|
||||
// 171.9p vs 170.9p over a 1.23 mi delta: net +£0.0305.
|
||||
// 171.9p vs 170.9p over a 1.23 mi delta: the small saving remains within tolerance.
|
||||
let result = try briefResult(candidatePrice: 170.9, extraMiles: 1.23)
|
||||
XCTAssertEqual(result.netSavingGBP, 0.030500, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.netSavingGBP, 0.03254252417853143, accuracy: 1e-9)
|
||||
XCTAssertEqual(result.status, .breakEven, "±5p reads as break even rather than a meaningless £0.03")
|
||||
XCTAssertEqual(result.headline(), "Break even")
|
||||
}
|
||||
|
||||
func testBreakEvenToleranceDecidesTheClassificationAtTheBoundary() throws {
|
||||
let net = -0.168911
|
||||
let net = -0.166869
|
||||
// A tolerance wider than the loss → break even; narrower → worse off.
|
||||
let lenient = try FuelSavingsCalculator.calculate(
|
||||
mpg: 30,
|
||||
@@ -187,7 +253,7 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
func testMoneyIsRoundedOnlyForDisplay() throws {
|
||||
// Full precision retained internally…
|
||||
let result = try briefResult(candidatePrice: 172.9, extraMiles: 2.8)
|
||||
XCTAssertEqual(result.netSavingGBP, -1.082658, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.netSavingGBP, -1.080639, accuracy: 1e-6)
|
||||
XCTAssertNotEqual(result.netSavingGBP, -1.08, "the stored value must not be pre-rounded")
|
||||
// …and rounded to two places only when shown.
|
||||
XCTAssertEqual(FuelSavingsFormat.money(1.082658), "£1.08")
|
||||
@@ -237,12 +303,12 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
baselineJourneyMiles: 2.0,
|
||||
candidateJourneyMiles: 7.0
|
||||
)
|
||||
XCTAssertEqual(result.fillLitres, 27.416038, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.grossSavingGBP, 1.919123, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.fillLitres, 28.797696, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.grossSavingGBP, 2.015839, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.extraDrivingCostGBP, 0.701613, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.netSavingGBP, 1.217509, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.netSavingGBP, 1.314226, accuracy: 1e-6)
|
||||
XCTAssertEqual(result.status, .worthTheDrive)
|
||||
XCTAssertEqual(result.headline(), "£1.22 better off after travel")
|
||||
XCTAssertEqual(result.headline(), "Save £1.31")
|
||||
}
|
||||
|
||||
func testNearerCandidateIsNeverChargedExtraTravel() throws {
|
||||
@@ -270,9 +336,9 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
baselineJourneyMiles: 0.8,
|
||||
candidateJourneyMiles: 3.6
|
||||
)
|
||||
XCTAssertEqual(sixty.grossSavingGBP, -0.349040, accuracy: 1e-6, "MPG must not touch the pump saving")
|
||||
XCTAssertEqual(sixty.grossSavingGBP, -0.347021, accuracy: 1e-6, "MPG must not touch the pump saving")
|
||||
XCTAssertEqual(sixty.extraDrivingCostGBP, 0.366809, accuracy: 1e-6)
|
||||
XCTAssertEqual(sixty.netSavingGBP, -0.715849, accuracy: 1e-6)
|
||||
XCTAssertEqual(sixty.netSavingGBP, -0.713830, accuracy: 1e-6)
|
||||
|
||||
let fortyFive = try FuelSavingsCalculator.calculate(
|
||||
mpg: 45,
|
||||
@@ -283,7 +349,7 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
candidateJourneyMiles: 3.6
|
||||
)
|
||||
XCTAssertEqual(fortyFive.extraDrivingCostGBP, 0.489078, accuracy: 1e-6)
|
||||
XCTAssertEqual(fortyFive.netSavingGBP, -0.838119, accuracy: 1e-6)
|
||||
XCTAssertEqual(fortyFive.netSavingGBP, -0.836100, accuracy: 1e-6)
|
||||
}
|
||||
|
||||
func testDifferentFillBudgetsScaleOnlyThePumpSaving() throws {
|
||||
@@ -295,10 +361,10 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
baselineJourneyMiles: 0.8,
|
||||
candidateJourneyMiles: 3.6
|
||||
)
|
||||
XCTAssertEqual(forty.fillLitres, 23.269343, accuracy: 1e-6, "£40 buys 23.27 L at 171.9p")
|
||||
XCTAssertEqual(forty.grossSavingGBP, -0.232693, accuracy: 1e-6)
|
||||
XCTAssertEqual(forty.fillLitres, 23.134760, accuracy: 1e-6, "£40 buys 23.13 L at the candidate price")
|
||||
XCTAssertEqual(forty.grossSavingGBP, -0.231348, accuracy: 1e-6)
|
||||
XCTAssertEqual(forty.extraDrivingCostGBP, 0.733618, accuracy: 1e-6, "the journey cost is budget-independent")
|
||||
XCTAssertEqual(forty.netSavingGBP, -0.966311, accuracy: 1e-6)
|
||||
XCTAssertEqual(forty.netSavingGBP, -0.964965, accuracy: 1e-6)
|
||||
|
||||
let ninety = try FuelSavingsCalculator.calculate(
|
||||
mpg: 30,
|
||||
@@ -308,9 +374,9 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
baselineJourneyMiles: 0.8,
|
||||
candidateJourneyMiles: 3.6
|
||||
)
|
||||
XCTAssertEqual(ninety.fillLitres, 52.356021, accuracy: 1e-6)
|
||||
XCTAssertEqual(ninety.grossSavingGBP, -0.523560, accuracy: 1e-6)
|
||||
XCTAssertEqual(ninety.netSavingGBP, -1.257178, accuracy: 1e-6)
|
||||
XCTAssertEqual(ninety.fillLitres, 52.053210, accuracy: 1e-6)
|
||||
XCTAssertEqual(ninety.grossSavingGBP, -0.520532, accuracy: 1e-6)
|
||||
XCTAssertEqual(ninety.netSavingGBP, -1.254150, accuracy: 1e-6)
|
||||
}
|
||||
|
||||
func testFillUpInLitresIsFixedRegardlessOfPrice() throws {
|
||||
@@ -370,7 +436,7 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
journey: journey(2.8),
|
||||
baselineJourney: journey(0.8)
|
||||
)
|
||||
XCTAssertEqual(both?.result?.netSavingGBP ?? 0, -0.168911, accuracy: 1e-6)
|
||||
XCTAssertEqual(both?.result?.netSavingGBP ?? 0, -0.166869, accuracy: 1e-6)
|
||||
}
|
||||
|
||||
func testMixedRouteBasisIsReportedAsAnEstimate() {
|
||||
@@ -393,7 +459,7 @@ final class FuelSavingsCalculationAuditTests: XCTestCase {
|
||||
XCTAssertEqual(mixed?.result?.distanceBasis, .straightLine,
|
||||
"one unmeasured leg makes the whole estimate an estimate")
|
||||
XCTAssertEqual(mixed?.result?.journeyConfidence, .estimated)
|
||||
XCTAssertEqual(mixed?.result?.headline(compact: true), "Approx. £0.17 worse off after travel")
|
||||
XCTAssertEqual(mixed?.result?.headline(compact: true), "Approx. Costs £0.17 more")
|
||||
}
|
||||
|
||||
func testBaselineStationIsLabelledClosestStationNotBreakEven() {
|
||||
|
||||
@@ -284,9 +284,9 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
/// (171.9p, 0.4 mi), candidate Shell Whetley Hill (167.9p, 3.8 mi).
|
||||
///
|
||||
/// Whetley Hill is 4p/litre cheaper, yet it is WORSE OFF — and that is
|
||||
/// correct, not a calculation bug: £60 buys 34.90 L at 171.9p, so the
|
||||
/// cheaper pump saves 34.90 × 4p = £1.40, while the extra 6.8 return miles
|
||||
/// burn 6.8/30 × 4.54609 = 1.03 L at 167.9p = £1.73. Net ≈ −£0.33.
|
||||
/// correct, not a calculation bug: £60 buys 35.74 L at 167.9p, so the
|
||||
/// cheaper pump saves 35.74 × 4p = £1.43, while the extra 6.8 return miles
|
||||
/// burn 6.8/30 × 4.54609 = 1.03 L at 167.9p = £1.73. Net ≈ −£0.30.
|
||||
func testCheaperStationFurtherAwayIsWorseOffAfterTravel() {
|
||||
let baseline = station("rontec-shelf", price: 171.9)
|
||||
let candidate = station("shell-whetley-hill", price: 167.9)
|
||||
@@ -304,16 +304,16 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
guard let result = availability?.result else {
|
||||
return XCTFail("expected an estimate, got \(String(describing: availability))")
|
||||
}
|
||||
XCTAssertEqual(result.fillLitres, 34.904, accuracy: 0.005,
|
||||
"the £60 budget buys litres at the BASELINE pump price")
|
||||
XCTAssertEqual(result.grossSavingGBP, 1.396, accuracy: 0.005)
|
||||
XCTAssertEqual(result.fillLitres, 35.736, accuracy: 0.005,
|
||||
"the £60 budget buys litres at the candidate pump price")
|
||||
XCTAssertEqual(result.grossSavingGBP, 1.429, accuracy: 0.005)
|
||||
XCTAssertEqual(result.extraDistanceMiles, 6.8, accuracy: 0.001,
|
||||
"only the return-trip DELTA counts — the shared journey is never counted twice")
|
||||
XCTAssertEqual(result.extraDrivingCostGBP, 1.730, accuracy: 0.005)
|
||||
XCTAssertEqual(result.netSavingGBP, -0.334, accuracy: 0.005)
|
||||
XCTAssertEqual(result.netSavingGBP, -0.301, accuracy: 0.005)
|
||||
XCTAssertEqual(result.status, .notWorthTheDrive)
|
||||
XCTAssertEqual(result.journeyConfidence, .estimated)
|
||||
XCTAssertEqual(result.headline(compact: true), "Approx. £0.33 worse off after travel")
|
||||
XCTAssertEqual(result.headline(compact: true), "Approx. Costs £0.30 more")
|
||||
}
|
||||
|
||||
func testMeasuredRoadRoutesDropTheEstimateMarker() {
|
||||
@@ -332,8 +332,8 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(availability?.result?.distanceBasis, .roadRoute)
|
||||
XCTAssertEqual(availability?.result?.journeyConfidence, .confirmed)
|
||||
XCTAssertEqual(availability?.result?.headline(compact: true), "£0.33 worse off after travel")
|
||||
XCTAssertEqual(availability?.result?.headline(), "£0.33 worse off after travel")
|
||||
XCTAssertEqual(availability?.result?.headline(compact: true), "Costs £0.30 more")
|
||||
XCTAssertEqual(availability?.result?.headline(), "Costs £0.30 more")
|
||||
}
|
||||
|
||||
func testBaselineRowIsLabelledClosestStation() {
|
||||
@@ -375,10 +375,10 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
return XCTFail("expected an estimate, got \(String(describing: availability))")
|
||||
}
|
||||
XCTAssertEqual(result.status, .worthTheDrive)
|
||||
// £60 buys 37.5 L at 160p; 10p/litre cheaper saves £3.75; 0.4 extra
|
||||
// return miles cost ~£0.09. Net ≈ £3.66.
|
||||
XCTAssertEqual(result.netSavingGBP, 3.659, accuracy: 0.005)
|
||||
XCTAssertEqual(result.headline(compact: true), "Approx. £3.66 better off after travel")
|
||||
// £60 buys 40 L at 150p; 10p/litre cheaper saves £4.00; 0.4 extra
|
||||
// return miles cost ~£0.09. Net ≈ £3.91.
|
||||
XCTAssertEqual(result.netSavingGBP, 3.909, accuracy: 0.005)
|
||||
XCTAssertEqual(result.headline(compact: true), "Approx. Save £3.91")
|
||||
}
|
||||
|
||||
func testNeutralResultHeadlineIsBreakEven() {
|
||||
@@ -413,7 +413,7 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
netSavingGBP: 0.52,
|
||||
status: .worthTheDrive,
|
||||
distanceBasis: .roadRoute)
|
||||
XCTAssertEqual(saving.headline(), "£0.52 better off after travel")
|
||||
XCTAssertEqual(saving.headline(), "Save £0.52")
|
||||
|
||||
let loss = FuelSavingsResult(fillLitres: 34.9,
|
||||
grossSavingGBP: 1.40,
|
||||
@@ -422,7 +422,7 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
netSavingGBP: -0.31,
|
||||
status: .notWorthTheDrive,
|
||||
distanceBasis: .roadRoute)
|
||||
XCTAssertEqual(loss.headline(), "£0.31 worse off after travel")
|
||||
XCTAssertEqual(loss.headline(), "Costs £0.31 more")
|
||||
}
|
||||
|
||||
/// The sort must order by NET saving, not pump price: a pricier station can
|
||||
@@ -497,7 +497,7 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
status: .worthTheDrive,
|
||||
distanceBasis: .straightLine
|
||||
)
|
||||
XCTAssertEqual(saving.capsuleHeadline(), "Approx. £1.00 better off after travel")
|
||||
XCTAssertEqual(saving.capsuleHeadline(), "Approx. Save £1.00")
|
||||
|
||||
let worse = FuelSavingsResult(
|
||||
fillLitres: 30,
|
||||
@@ -507,7 +507,7 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
netSavingGBP: -0.31,
|
||||
status: .notWorthTheDrive
|
||||
)
|
||||
XCTAssertEqual(worse.capsuleHeadline(), "£0.31 worse off after travel")
|
||||
XCTAssertEqual(worse.capsuleHeadline(), "Costs £0.31 more")
|
||||
}
|
||||
|
||||
// MARK: - Estimate wording (Approx. labels)
|
||||
@@ -524,7 +524,7 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
status: .worthTheDrive,
|
||||
distanceBasis: .straightLine
|
||||
)
|
||||
XCTAssertEqual(saving.headline(), "Approx. £1.25 better off after travel")
|
||||
XCTAssertEqual(saving.headline(), "Approx. Save £1.25")
|
||||
|
||||
let loss = FuelSavingsResult(
|
||||
fillLitres: 30,
|
||||
@@ -535,7 +535,7 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
status: .notWorthTheDrive,
|
||||
distanceBasis: .straightLine
|
||||
)
|
||||
XCTAssertEqual(loss.headline(), "Approx. £0.77 worse off after travel")
|
||||
XCTAssertEqual(loss.headline(), "Approx. Costs £0.77 more")
|
||||
}
|
||||
|
||||
/// A confirmed road-route comparison must never carry the marker — in either
|
||||
@@ -551,7 +551,7 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
distanceBasis: .roadRoute,
|
||||
journeyConfidence: .confirmed
|
||||
)
|
||||
XCTAssertEqual(saving.headline(), "£1.25 better off after travel")
|
||||
XCTAssertEqual(saving.headline(), "Save £1.25")
|
||||
|
||||
let loss = FuelSavingsResult(
|
||||
fillLitres: 30,
|
||||
@@ -563,7 +563,7 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
distanceBasis: .roadRoute,
|
||||
journeyConfidence: .confirmed
|
||||
)
|
||||
XCTAssertEqual(loss.headline(), "£0.77 worse off after travel")
|
||||
XCTAssertEqual(loss.headline(), "Costs £0.77 more")
|
||||
|
||||
for headline in [saving.headline(), loss.headline(), saving.capsuleHeadline()] {
|
||||
XCTAssertFalse(headline.contains("Approx"), "\"\(headline)\" must not claim to be an estimate")
|
||||
@@ -597,7 +597,7 @@ final class FuelSavingsEstimateTests: XCTestCase {
|
||||
status: .notWorthTheDrive,
|
||||
distanceBasis: .straightLine
|
||||
)
|
||||
XCTAssertEqual(estimated.spokenHeadline(), "Approximately £0.77 worse off after travel")
|
||||
XCTAssertEqual(estimated.spokenHeadline(), "Approximately Costs £0.77 more")
|
||||
|
||||
XCTAssertEqual(
|
||||
FuelSavingsFormat.extraTravelSpokenLabel(extraDistanceMiles: 6.4, unit: .miles, confidence: .estimated),
|
||||
|
||||
@@ -8,15 +8,15 @@ final class FuelSavingsCalculatorTests: XCTestCase {
|
||||
XCTAssertEqual(FuelSavingsCalculator.fuelUsedLitres(distanceMiles: 10, mpg: 45), 1.0102, accuracy: 0.0001)
|
||||
}
|
||||
|
||||
func testPoundsBudgetConvertsToLitresUsingBaselinePrice() throws {
|
||||
func testPoundsBudgetConvertsToLitresUsingGivenPrice() throws {
|
||||
let amount = FuelSavingsFillAmount(value: 40, unit: .pounds)
|
||||
let litres = try FuelSavingsCalculator.fillLitres(amount: amount, baselinePricePencePerLitre: 160)
|
||||
let litres = try FuelSavingsCalculator.fillLitres(amount: amount, pricePencePerLitre: 160)
|
||||
XCTAssertEqual(litres, 25.0, accuracy: 0.0001)
|
||||
}
|
||||
|
||||
func testLitresAmountPassesThrough() throws {
|
||||
let amount = FuelSavingsFillAmount(value: 35, unit: .litres)
|
||||
let litres = try FuelSavingsCalculator.fillLitres(amount: amount, baselinePricePencePerLitre: 160)
|
||||
let litres = try FuelSavingsCalculator.fillLitres(amount: amount, pricePencePerLitre: 160)
|
||||
XCTAssertEqual(litres, 35, accuracy: 0.0001)
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@ final class FuelSavingsCalculatorTests: XCTestCase {
|
||||
baselineJourneyMiles: 2,
|
||||
candidateJourneyMiles: 8
|
||||
)
|
||||
XCTAssertEqual(result.fillLitres, 25, accuracy: 0.0001)
|
||||
XCTAssertEqual(result.grossSavingGBP, 2.50, accuracy: 0.0001)
|
||||
XCTAssertEqual(result.fillLitres, 26.6667, accuracy: 0.0001)
|
||||
XCTAssertEqual(result.grossSavingGBP, 2.6667, accuracy: 0.0001)
|
||||
XCTAssertEqual(result.extraDistanceMiles, 6, accuracy: 0.0001)
|
||||
XCTAssertEqual(result.extraDrivingCostGBP, 0.9092, accuracy: 0.0001)
|
||||
XCTAssertEqual(result.netSavingGBP, 1.5908, accuracy: 0.0001)
|
||||
XCTAssertEqual(result.netSavingGBP, 1.7574, accuracy: 0.0001)
|
||||
XCTAssertEqual(result.status, .worthTheDrive)
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ final class FuelSavingsCalculatorTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testInvalidInputsRejected() {
|
||||
XCTAssertThrowsError(try FuelSavingsCalculator.fillLitres(amount: FuelSavingsFillAmount(value: 40, unit: .pounds), baselinePricePencePerLitre: 0))
|
||||
XCTAssertThrowsError(try FuelSavingsCalculator.fillLitres(amount: FuelSavingsFillAmount(value: 40, unit: .pounds), pricePencePerLitre: 0))
|
||||
XCTAssertThrowsError(try FuelSavingsCalculator.calculate(mpg: 0, amount: FuelSavingsFillAmount(value: 40, unit: .pounds), baselinePricePencePerLitre: 160, candidatePricePencePerLitre: 150, baselineJourneyMiles: 1, candidateJourneyMiles: 2))
|
||||
XCTAssertThrowsError(try FuelSavingsCalculator.calculate(mpg: 500, amount: FuelSavingsFillAmount(value: 40, unit: .pounds), baselinePricePencePerLitre: 160, candidatePricePencePerLitre: 150, baselineJourneyMiles: 1, candidateJourneyMiles: 2))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user