Solution to basic unit tests I'm working my way through an intermediate Python course on Pluralsight that focuses on unit testing and just finished my first assignment.

Basically the course itself focuses on teaching you how to write correct test-cases and gives you a baseline of the class to start solving the tests by yourself.

To clarify:

I'm more concerned on the implemented solutions to the test-cases than on the test-cases themselves. Sorry for any confusion!



I was hoping that I could get some feedback on my implemented solutions to the test-cases (they all are passing):

import unittest

from phonebook import Phonebook

class PhoneBookTest(unittest.TestCase):

    def setUp(self):
        self.phonebook = Phonebook()

    def test_phonebook_with_normal_entries_is_consitent(self):
        self.phonebook.add("Bob", "12345")
        self.phonebook.add("Mary", "012345")
        self.assertTrue(self.phonebook.is_consistent())

    def test_phonebook_with_duplicate_entries_is_inconsitent(self):
        self.phonebook.add("Bob", "12345")
        self.phonebook.add("Sue", "12345")  # identical to Bob
        self.assertFalse(self.phonebook.is_consistent())

    def test_phonebook_with_same_prefix_is_inconsistent(self):
        self.phonebook.add("Bob", "12345")
        self.phonebook.add("Sue", "123")  # prefix of Bob
        self.assertFalse(self.phonebook.is_consistent())




Here is my actual Phonebook class:

class Phonebook:

    def __init__(self):
        self._entries = {}

    def add(self, name, number):
        self._entries[name] = number

    def lookup(self, name):
        return self._entries[name]

    def is_consistent(self):
        if not self._entries:
            return True
        else:
            if self.check_duplicate():
                if self.check_prefix():
                    return True
        return False

    def check_duplicate(self):
        seen = set()
        for x in self.get_values():
            if x not in seen:
                seen.add(x)
            else:
                return False
        return True

    def check_prefix(self):
        prefixes = []
        for contact_number in self.get_values():
            if contact_number not in map(lambda number: number[0:len(contact_number)], prefixes):
                prefixes.append(contact_number)
            else:
                return False
        return True

    def get_values(self):
        return self._entries.values()


I'm mostly concerned of refactoring and the check_function and check_prefix functions performance and overall implementation. However I still consider myself to be a beginner, so all help would be appreciated! :)

Any feedback would be great!
Bug: The result of check_prefix depends on the order of values. Basically, it compares each pair of values once, but truncates only one of the two for comparison. On my Python 3.5 your test fails occasionally.
Duplicate values are also prefixes of one another. It is not necessary for is_consistent to check for both.
It is not necessary to handle the empty phonebook as a special case in is_consistent as the check functions return True swiftly anyway in that case. Thus the function can be simplified to

def is_consistent(self):
    return self.check_prefix()

A more efficient solution for check_prefix would be to sort the values and compare adjacent ones. Making use of pairwise from Itertool recipes, and the fact that the prefix will sort first:

def check_prefix(self):
    return not any(b.startswith(a) 
                   for a, b in pairwise(sorted(self.get_values())))