doubles/call_count_accumulator.py (66 lines of code) (raw):
def pluralize(word, count):
return word if count == 1 else word + 's'
class CallCountAccumulator(object):
def __init__(self):
self._call_count = 0
def set_exact(self, n):
"""Set an exact call count expectation
:param integer n:
"""
self._exact = n
def set_minimum(self, n):
"""Set a minimum call count expectation
:param integer n:
"""
self._minimum = n
def set_maximum(self, n):
"""Set a maximum call count expectation
:param integer n:
"""
self._maximum = n
def has_too_many_calls(self):
"""Test if there have been too many calls
:rtype boolean
"""
if self.has_exact and self._call_count > self._exact:
return True
if self.has_maximum and self._call_count > self._maximum:
return True
return False
def has_too_few_calls(self):
"""Test if there have not been enough calls
:rtype boolean
"""
if self.has_exact and self._call_count < self._exact:
return True
if self.has_minimum and self._call_count < self._minimum:
return True
return False
def has_incorrect_call_count(self):
"""Test if there have not been a valid number of calls
:rtype boolean
"""
return self.has_too_few_calls() or self.has_too_many_calls()
def has_correct_call_count(self):
"""Test if there have been a valid number of calls
:rtype boolean
"""
return not self.has_incorrect_call_count()
def never(self):
"""Test if the number of expect is 0
:rtype: boolean
"""
return self.has_exact and self._exact == 0
def called(self):
"""Increment the call count"""
self._call_count += 1
return self
@property
def count(self):
"""Extract the current call count
:rtype integer
"""
return self._call_count
@property
def has_minimum(self):
"""Test if self has a minimum call count set
:rtype boolean
"""
return getattr(self, '_minimum', None) is not None
@property
def has_maximum(self):
"""Test if self has a maximum call count set
:rtype boolean
"""
return getattr(self, '_maximum', None) is not None
@property
def has_exact(self):
"""Test if self has an exact call count set
:rtype boolean
"""
return getattr(self, '_exact', None) is not None
def _restriction_string(self):
"""Get a string explaining the expectation currently set
e.g `at least 5 times`, `at most 1 time`, or `2 times`
:rtype string
"""
if self.has_minimum:
string = 'at least '
value = self._minimum
elif self.has_maximum:
string = 'at most '
value = self._maximum
elif self.has_exact:
string = ''
value = self._exact
return (string + '{} {}').format(
value,
pluralize('time', value)
)
def error_string(self):
"""Returns a well formed error message
e.g at least 5 times but was called 4 times
:rtype string
"""
if self.has_correct_call_count():
return ''
return '{} instead of {} {} '.format(
self._restriction_string(),
self.count,
pluralize('time', self.count)
)