Last active
October 1, 2016 14:31
-
-
Save ByteJuggler/f35154f9584d7cbd65afb89ffc2691f1 to your computer and use it in GitHub Desktop.
Py.Test test cases for email validation (& CodeEval challenge 35)
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
#!/usr/bin/env python | |
# -*- coding: windows-1252 -*- | |
# Copyright © 2016 Walter Prins. All rights reserved. | |
# Created: 2016-10-01 | |
# Updated: 2016-10-01 | |
"""Test cases for a hypothetical module called "email_validation" and a Python | |
callable (class) that will tell you if a given email is valid or not. My own | |
implementation is ultimately based on the RFC's and a state machine, | |
and passes against the below test suite. It also passes the CodeEval challenge | |
below (a question about which prodded me into having a look at this in the | |
first place): | |
https://www.codeeval.com/open_challenges/35/ | |
Note: The additional output e.g. "resultcode", "invalidchar" and "invalidpos" | |
is not required by the challenge, I've added it because my implementation | |
is based on an earlier Object Pascal implementation that similarly provides | |
more information than just a true/false output. Hence I therefore wanted to keep | |
it around for fun and profit in my Python implementation as well, and also | |
thought it would be fun to write a Python solution that seamlessly can work | |
for the CodeEval challenge API,and yet also retains the higher fidelity feedback | |
if you want it (telling you what's actually wrong), if desired. | |
If however these extra properties/members give you a headache and | |
you just want to use these tests to help your development for the above | |
challenge, then obviously please rip them out and keep only the bool checks! | |
""" | |
from email_validation import email_valid, ResultCode | |
def testAllowBlankProperty(): | |
"""In my class I allow the caller to specify whether they'd like to consider | |
a blank email as valid or not. Check that this works""" | |
result = email_valid('', True) | |
assert result == True | |
assert result.resultcode == ResultCode.EmailValid | |
assert result.invalidchar == None | |
assert result.invalidpos == None | |
result = email_valid('', False) | |
assert result == False | |
assert result.resultcode == ResultCode.BlankAddressNotAllowed | |
assert result.invalidchar == None | |
assert result.invalidpos == 0 | |
def testQuotedWSpaceNameEmail(): | |
"""Emails can contain space in the name part, provided they're quoted.""" | |
result = email_valid('"joe bloggs"@b.c') | |
assert result == True | |
assert result.resultcode == ResultCode.EmailValid | |
result = email_valid('joe bloggs@b.c') | |
assert result == False | |
assert result.resultcode == ResultCode.InvalidCharacter | |
assert result.invalidchar == ' ' | |
assert result.invalidpos == 3 | |
def testShortestPossibleEmail(): | |
"""Emails have to have at least 2 subdomain parts, so this corresponds to | |
the shortest email address that is valid.""" | |
result = email_valid('a@b.c') | |
assert result == True | |
assert result.resultcode == ResultCode.EmailValid | |
assert result.invalidchar == None | |
assert result.invalidpos == None | |
def testBadlyTerminatedEmail(): | |
"""Here's several inputs that constitute partially valid or badly terminated | |
email addresses. E.g. Either they're incomplete, or they've been badly | |
terminated, either way they're not valid as-is.""" | |
# Email cannot terminate on a period | |
result = email_valid('a@b.c.') | |
assert result == False | |
assert result.resultcode == ResultCode.EmailIncompleteOrBadlyTerminated | |
assert result.invalidchar == None | |
#We expect the call to tell us that the last character is where the problem | |
#occurs, even though it's not actually invalid: | |
#(One might equally design the call/library to not do this... wouldn't have | |
# too many arguments from me if you preferred it the other way, e.g. | |
# always have invalidpos None unless invalidchar is not None also... still | |
# as of this writing I thought this would be more informative so there you | |
# go. | |
assert result.invalidpos == 5 | |
# Email cannot terminate on a hyphen | |
result = email_valid('a@b.c-') | |
assert result == False | |
assert result.resultcode == ResultCode.EmailIncompleteOrBadlyTerminated | |
assert result.invalidchar == None | |
assert result.invalidpos == 5 | |
# ... likewise double hyphen is invalid. | |
result = email_valid('a@b.c--') | |
assert result == False | |
assert result.resultcode == ResultCode.EmailIncompleteOrBadlyTerminated | |
assert result.invalidchar == None | |
assert result.invalidpos == 6 | |
# Some further test cases that break some other validators. | |
# Can't terminate on second @, it is outright not valid. | |
result = email_valid('a@b.c@') | |
assert result == False | |
assert result.resultcode == ResultCode.InvalidCharacter | |
assert result.invalidchar == '@' | |
assert result.invalidpos == 5 | |
# Can't terminate on space, it is outright not valid. | |
result = email_valid('a@b.c ') | |
assert result == False | |
assert result.resultcode == ResultCode.InvalidCharacter | |
assert result.invalidchar == ' ' | |
assert result.invalidpos == 5 | |
def testTooShortEmail(): | |
"""Test that too short emails are caught appropriately.""" | |
result = email_valid('a@b') | |
assert result == False | |
assert result.resultcode == ResultCode.EmailMustHave2SubDomains | |
assert result.invalidchar == None | |
assert result.invalidpos == None | |
def testQuotedWSpaceSubdomainEmail(): | |
"""Subdomains may not contain spaces, even if quoted.""" | |
result = email_valid('a@"my company".c') | |
assert result == False | |
assert result.resultcode == ResultCode.InvalidCharacter | |
assert result.invalidchar == '"' | |
assert result.invalidpos == 2 | |
def testHyphenatedEmail(): | |
"""Various test cases with hyphens that trip up some validators but are | |
in fact valid email addresses and should be allowed:""" | |
result = email_valid('a-b@b.c') | |
assert result == True | |
assert result.resultcode == ResultCode.EmailValid | |
assert result.invalidchar == None | |
assert result.invalidpos == None | |
result = email_valid('a@b-c.d') | |
assert result == True | |
assert result.resultcode == ResultCode.EmailValid | |
assert result.invalidchar == None | |
assert result.invalidpos == None | |
result = email_valid('a@b--c.d') | |
assert result == True | |
assert result.resultcode == ResultCode.EmailValid | |
assert result.invalidchar == None | |
assert result.invalidpos == None | |
result = email_valid('a-@b.c') | |
assert result == True | |
assert result.resultcode == ResultCode.EmailValid | |
assert result.invalidchar == None | |
assert result.invalidpos == None | |
def testUnderscoredEmail(): | |
"""Various test cases with underscores that trip up some validators. | |
Some valid, some not.""" | |
result = email_valid('a_b@b.c') | |
assert result == True | |
assert result.resultcode == ResultCode.EmailValid | |
assert result.invalidchar == None | |
assert result.invalidpos == None | |
result = email_valid('a@b_c.d') | |
assert result == False | |
assert result.resultcode == ResultCode.InvalidCharacter | |
assert result.invalidchar == '_' | |
assert result.invalidpos == 3 | |
result = email_valid('a_@b.c') | |
assert result == True | |
assert result.resultcode == ResultCode.EmailValid | |
assert result.invalidchar == None | |
assert result.invalidpos == None | |
def test_CodeEval_Cases(): | |
result = email_valid('foo@bar.com') | |
assert result == True | |
assert result.resultcode == ResultCode.EmailValid | |
assert result.invalidchar == None | |
assert result.invalidpos == None | |
result = email_valid('this is not an email id') | |
assert result == False | |
assert result.resultcode == ResultCode.InvalidCharacter | |
assert result.invalidchar == ' ' | |
assert result.invalidpos == 4 | |
result = email_valid('admin#codeeval.com') | |
assert result == False | |
assert result.resultcode == ResultCode.EmailIncompleteOrBadlyTerminated | |
assert result.invalidchar == None | |
assert result.invalidpos == 17 | |
result = email_valid('good123@bad.com') | |
assert result == True | |
assert result.resultcode == ResultCode.EmailValid | |
assert result.invalidchar == None | |
assert result.invalidpos == None | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment