Created
January 30, 2014 09:09
-
-
Save agonzalezro/8705016 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import unittest | |
PRICE_KEY = 'price' | |
OFFER_AFTER_KEY = 'offer_after' | |
DISCOUNT_KEY = 'discount' | |
PRODUCT_PRICING_DETAILS = { | |
'A': { | |
PRICE_KEY: 50, | |
OFFER_AFTER_KEY: 3, | |
DISCOUNT_KEY: 20 | |
}, | |
'B': { | |
PRICE_KEY: 30, | |
OFFER_AFTER_KEY: 2, | |
DISCOUNT_KEY: 15 | |
}, | |
'C': { | |
PRICE_KEY: 20 | |
}, | |
'D': { | |
PRICE_KEY: 15 | |
} | |
} | |
class ProductNotFound(Exception): | |
pass | |
def _can_apply_discount_to_product(product): | |
return DISCOUNT_KEY in PRODUCT_PRICING_DETAILS[product] | |
def _price_for_product(product): | |
if product in PRODUCT_PRICING_DETAILS: | |
return PRODUCT_PRICING_DETAILS[product][PRICE_KEY] | |
raise ProductNotFound | |
def _get_discount(product, quantity): | |
discount_total = 0 | |
if _can_apply_discount_to_product(product): | |
discount = PRODUCT_PRICING_DETAILS[product][DISCOUNT_KEY] | |
how_many_times_apply = ( | |
quantity / PRODUCT_PRICING_DETAILS[product][OFFER_AFTER_KEY] | |
) | |
discount_total = discount * how_many_times_apply | |
return discount_total | |
def price_for_basket(basket): | |
counters = {} | |
total = 0 | |
total_discount = 0 | |
for product in basket: | |
total += _price_for_product(product) | |
counters.setdefault(product, 0) | |
counters[product] += 1 | |
for product, quantity in counters.iteritems(): | |
total_discount += _get_discount(product, quantity) | |
return total - total_discount | |
class Test(unittest.TestCase): | |
def test_no_products(self): | |
"""No products given should return 0.""" | |
self.assertEqual(price_for_basket(''), 0) | |
def test_one_product_type_A(self): | |
"""Test that given a product type A the total is 50 pounds.""" | |
self.assertEqual(price_for_basket('A'), 50) | |
def test_two_products_type_A(self): | |
"""Test that given two products type A the total is 100 pounds.""" | |
self.assertEqual(price_for_basket('AA'), 100) | |
def test_product_type_A_offer(self): | |
"""Test that given 3 or more products type A the offer is applied.""" | |
self.assertEqual(price_for_basket('AAA'), 130) | |
self.assertEqual(price_for_basket('AAAA'), 180) | |
self.assertEqual(price_for_basket('AAAAAA'), 260) | |
def test_one_product_type_B(self): | |
"""Test that one product B have a value of 30.""" | |
self.assertEqual(price_for_basket('B'), 30) | |
def test_two_products_type_B(self): | |
"""Test that 2 product of type B have a value of 45 (discount applied). | |
""" | |
self.assertEqual(price_for_basket('BB'), 45) | |
def test_product_type_B_offers(self): | |
"""Test that discounts for the product B are applied.""" | |
self.assertEqual(price_for_basket('BBBB'), 90) | |
self.assertEqual(price_for_basket('BBBBB'), 120) | |
def test_product_type_A_and_B(self): | |
"""Test that a mixed basket return proper values.""" | |
self.assertEqual(price_for_basket('AB'), 80) | |
def test_special_offer_A_and_single_B(self): | |
"""Test that a basket with 3 As and one B is going to apply the | |
discount for A and a normal price for B. | |
""" | |
self.assertEqual(price_for_basket('ABAA'), 160) | |
def test_one_product_type_C(self): | |
"""Test that giving one product of type C the value of the basket will | |
be 20. | |
""" | |
self.assertEqual(price_for_basket('C'), 20) | |
def test_two_products_type_C(self): | |
"""Test that giving two products of type C no disccounts are going to | |
be applied. | |
""" | |
self.assertEqual(price_for_basket('CC'), 40) | |
def test_one_product_type_D(self): | |
"""Test that one product of type D is going to have a value of 15.""" | |
self.assertEqual(price_for_basket('D'), 15) | |
def test_mixed_basket(self): | |
expected = 115 | |
self.assertEqual(price_for_basket('ABCD'), expected) | |
self.assertEqual(price_for_basket('DCBA'), expected) | |
self.assertEqual(price_for_basket('BDCA'), expected) | |
def test_non_expected_product(self): | |
"""Test that an unexpected product raises a ProductNotFound exception. | |
""" | |
self.assertRaises(ProductNotFound, price_for_basket, 'E') | |
if __name__ == '__main__': | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment