I am practicing test-driven development in Python. Feedback about both the tests and the code is appreciated. I'm using luhn algorithm and regex to check credit card numbers for validity.
Here are the tests:
from unittest import TestCase import luhn_check class TestLuhnCheck(TestCase): def setUp(self): pass def test_known_sum(self): self.assertEquals(67, luhn_check.check_sum("7992739871")) def test_check_digit(self): self.assertEquals(3, luhn_check.find_check_digit("7992739871")) def test_check_valid(self): self.assertFalse(luhn_check.is_luhn_valid("abcdefg")) self.assertTrue(luhn_check.is_luhn_valid("79927398713")) def test_check_invalid(self): self.assertFalse(luhn_check.is_luhn_valid("79927398714")) def test_regex(self): self.assertTrue(luhn_check.check_regex("346340033233241")) self.assertFalse(luhn_check.check_regex("996340033233241")) def test_check_cc(self): #amex self.assertTrue(luhn_check.is_valid_cc("346340033233241")) #discover self.assertTrue(luhn_check.is_valid_cc("6011066253550425")) #visa self.assertTrue(luhn_check.is_valid_cc("4485332611430235")) #mc self.assertTrue(luhn_check.is_valid_cc("5463393720504875")) #bad: self.assertFalse(luhn_check.is_valid_cc("abcdefg")) self.assertFalse(luhn_check.is_valid_cc("11abcdefg")) self.assertFalse(luhn_check.is_valid_cc("946340033233241")) self.assertFalse(luhn_check.is_valid_cc("546339372050487500")) and here is the module:
import re def sum_digits(numeric_string): return sum([int(d) for d in numeric_string]) def valid_length_cc(cc_candidate): return len(cc_candidate) == 16 or len(cc_candidate) == 15 def check_sum(numeric_string): odds = numeric_string[:-1][::-2] evens = numeric_string[::-2] return sum([int(i) for i in odds]) + sum([sum_digits(str(int(i) * 2)) for i in evens]) def find_check_digit(numeric_string): return (check_sum(numeric_string) * 9) % 10 def is_luhn_valid(candidate): if candidate.isdigit(): check_digit = int(candidate[-1:]) return (check_sum(candidate[:-1]) + check_digit) % 10 == 0 else: return False def is_valid_cc(candidate): return check_regex(candidate) and valid_length_cc(candidate) and is_luhn_valid(candidate) def check_regex(candidate): # are the digits correct? pattern = "^((4\d{3})|(5[1-5]\d{2})|(6011)|(7\d{3}))-?\d{4}-?\d{4}-?\d{4}|3[4,7]\d{13}$" r = re.compile(pattern) return bool(r.match(candidate))