From b76b4ac18847a19c9a226cac0a5f0b6309210f19 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Sun, 29 Jan 2017 18:15:19 +0000 Subject: [PATCH 1/5] luhn: Update tests - implement new tests as described in: https://github.com/exercism/x-common/blob/master/exercises/luhn/canonical-data.json --- exercises/luhn/luhn_test.py | 46 ++++++++++--------------------------- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/exercises/luhn/luhn_test.py b/exercises/luhn/luhn_test.py index 630b1c8ca1c..0aab3a4e5d8 100644 --- a/exercises/luhn/luhn_test.py +++ b/exercises/luhn/luhn_test.py @@ -1,48 +1,26 @@ -from collections import Counter import unittest from luhn import Luhn class LuhnTests(unittest.TestCase): - def test_addends(self): - # uses a Counter to avoid specifying order of return value - self.assertEqual(Counter([1, 4, 1, 4, 1]), - Counter(Luhn(12121).addends())) + def test_single_digit_strings_can_not_be_valid(self): + self.assertFalse(Luhn("1").is_valid()) - def test_addends_large(self): - # uses a Counter to avoid specifying order of return value - self.assertEqual(Counter([7, 6, 6, 1]), - Counter(Luhn(8631).addends())) + def test_a_single_zero_is_invalid(self): + self.assertFalse(Luhn("0").is_valid()) - def test_checksum1(self): - self.assertEqual(22, Luhn(4913).checksum()) + def test_valid_Canadian_SIN(self): + self.assertTrue(Luhn("046 454 286").is_valid()) - def test_ckecksum2(self): - self.assertEqual(21, Luhn(201773).checksum()) + def test_invalid_Canadian_SIN(self): + self.assertFalse(Luhn("046 454 287").is_valid()) - def test_invalid_number(self): - self.assertFalse(Luhn(738).is_valid()) + def test_invalid_credit_card(self): + self.assertFalse(Luhn("8273 1232 7352 0569").is_valid()) - def test_valid_number(self): - self.assertTrue(Luhn(8739567).is_valid()) - - def test_create_valid_number1(self): - self.assertEqual(1230, Luhn.create(123)) - - def test_create_valid_number2(self): - self.assertEqual(8739567, Luhn.create(873956)) - - def test_create_valid_number3(self): - self.assertEqual(8372637564, Luhn.create(837263756)) - - def test_is_valid_can_be_called_repeatedly(self): - # This test was added, because we saw many implementations - # in which the first call to is_valid() worked, but the - # second call failed(). - number = Luhn(8739567) - self.assertTrue(number.is_valid()) - self.assertTrue(number.is_valid()) + def test_valid_strings_with_a_non_digit_added_become_invalid(self): + self.assertFalse(Luhn("046a 454 286").is_valid()) if __name__ == '__main__': From b5ee75cfa615f0599f4c10b0a3ee51e2cbd113f2 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Sun, 29 Jan 2017 18:16:46 +0000 Subject: [PATCH 2/5] luhn: Update example to satisfy new tests --- exercises/luhn/example.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/exercises/luhn/example.py b/exercises/luhn/example.py index f6981cee5a6..4c062c04317 100644 --- a/exercises/luhn/example.py +++ b/exercises/luhn/example.py @@ -1,11 +1,11 @@ class Luhn(object): - def __init__(self, number): - self.number = number + def __init__(self, string): + self.string = string.replace(" ", "") def addends(self): def luhn_transform(n): return (2 * n - 9) if (n > 4) else (2 * n) - old_digits = [int(d) for d in str(self.number)] + old_digits = [int(d) for d in str(self.string)] return [(luhn_transform(n) if (i % 2 == 0) else n) for i, n in enumerate(old_digits, start=len(old_digits) % 2)] @@ -13,9 +13,6 @@ def checksum(self): return sum(self.addends()) def is_valid(self): + if len(self.string) <= 1 or not self.string.isdigit(): + return False return self.checksum() % 10 == 0 - - @staticmethod - def create(n): - diff = (10 - Luhn(n * 10).checksum()) % 10 - return 10 * n + diff From 50501453aa658f654947132066c270402a60f7dc Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Mon, 27 Feb 2017 22:02:58 +0000 Subject: [PATCH 3/5] luhn: Add canonical tests --- exercises/luhn/luhn_test.py | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/exercises/luhn/luhn_test.py b/exercises/luhn/luhn_test.py index 0aab3a4e5d8..40dfce6a881 100644 --- a/exercises/luhn/luhn_test.py +++ b/exercises/luhn/luhn_test.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import unittest from luhn import Luhn @@ -10,17 +12,38 @@ def test_single_digit_strings_can_not_be_valid(self): def test_a_single_zero_is_invalid(self): self.assertFalse(Luhn("0").is_valid()) - def test_valid_Canadian_SIN(self): - self.assertTrue(Luhn("046 454 286").is_valid()) + def test_a_simple_valid_SIN_that_remains_valid_if_reversed(self): + self.assertTrue(Luhn("059").is_valid()) + + def test_a_simple_valid_SIN_that_becomes_invalid_if_reversed(self): + self.assertTrue(Luhn("59").is_valid()) + + def test_a_valid_Canadian_SIN(self): + self.assertTrue(Luhn("055 444 285").is_valid()) def test_invalid_Canadian_SIN(self): - self.assertFalse(Luhn("046 454 287").is_valid()) + self.assertFalse(Luhn("055 444 286").is_valid()) def test_invalid_credit_card(self): self.assertFalse(Luhn("8273 1232 7352 0569").is_valid()) - def test_valid_strings_with_a_non_digit_added_become_invalid(self): - self.assertFalse(Luhn("046a 454 286").is_valid()) + def test_valid_strings_with_a_non_digit_included_become_invalid(self): + self.assertFalse(Luhn("055a 444 285").is_valid()) + + def test_valid_strings_with_punctuation_included_become_invalid(self): + self.assertFalse(Luhn("055-444-285").is_valid()) + + def test_valid_strings_with_symbols_included_become_invalid(self): + self.assertFalse(Luhn("055£ 444$ 285").is_valid()) + + def test_single_zero_with_space_is_invalid(self): + self.assertFalse(Luhn("0").is_valid()) + + def test_more_than_a_single_zero_is_valid(self): + self.assertTrue(Luhn("0000 0").is_valid()) + + def test_input_digit_9_is_correctly_converted_to_output_digit_9(self): + self.assertTrue(Luhn("091").is_valid()) if __name__ == '__main__': From 78d2a9bf877100cf0ffed168a86f4be13d4762f2 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Wed, 8 Mar 2017 22:21:05 +0000 Subject: [PATCH 4/5] luhn: Add test_is_valid_can_be_called_repeatedly --- exercises/luhn/luhn_test.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/exercises/luhn/luhn_test.py b/exercises/luhn/luhn_test.py index 40dfce6a881..4e3baa89a44 100644 --- a/exercises/luhn/luhn_test.py +++ b/exercises/luhn/luhn_test.py @@ -45,6 +45,15 @@ def test_more_than_a_single_zero_is_valid(self): def test_input_digit_9_is_correctly_converted_to_output_digit_9(self): self.assertTrue(Luhn("091").is_valid()) + def test_is_valid_can_be_called_repeatedly(self): + # Additional track specific test case + # This test was added, because we saw many implementations + # in which the first call to is_valid() worked, but the + # second call failed(). + number = Luhn(8739567) + self.assertTrue(number.is_valid()) + self.assertTrue(number.is_valid()) + if __name__ == '__main__': unittest.main() From a92f40e92fed9f6be98b4bfbafb1bb4448b7ba92 Mon Sep 17 00:00:00 2001 From: Rootul Patel Date: Wed, 8 Mar 2017 22:30:42 +0000 Subject: [PATCH 5/5] luhn: Use a_valid_Canadian_SIN for last test --- exercises/luhn/luhn_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/luhn/luhn_test.py b/exercises/luhn/luhn_test.py index 4e3baa89a44..42bfe368487 100644 --- a/exercises/luhn/luhn_test.py +++ b/exercises/luhn/luhn_test.py @@ -50,7 +50,7 @@ def test_is_valid_can_be_called_repeatedly(self): # This test was added, because we saw many implementations # in which the first call to is_valid() worked, but the # second call failed(). - number = Luhn(8739567) + number = Luhn("055 444 285") self.assertTrue(number.is_valid()) self.assertTrue(number.is_valid())