diff --git a/README.rst b/README.rst
index 572473bbd5387fadfb7893c071cf088b27dc8211..946defa2ef95016a333a9284e0810f26b9bd8eda 100644
--- a/README.rst
+++ b/README.rst
@@ -32,6 +32,10 @@ Contributions are welcome! Please add unit tests for new features
 or bug fixes.  To run all the unit tests run ``./setup test``.
 If you have `tox`_ installed, just run ``tox``.
 
+You can review `coverage`_ of added tests by running
+``coverage run setup.py test`` and then running
+``coverage report -m``.
+
 Note that tests are run on `Travis`_ for all supported python
 versions whenever the tree on github is pushed to.
 
@@ -54,5 +58,6 @@ Credits
 - `Kevin Lyda`_: Who got burned one too many times by broken crontabs.
 
 .. _`tox`: http://pypi.python.org/pypi/tox
+.. _`coverage`: http://pypi.python.org/pypi/coverage
 .. _`Travis`: http://travis-ci.org/#!/lyda/chkcrontab
 .. _`Kevin Lyda`: https://github.com/lyda
diff --git a/chkcrontab_lib.py b/chkcrontab_lib.py
index 8487362bd9a763f863335f8f70e87bc681818dc1..dded62dab1adc5ec0a4595e4c3e1d4e11f749a14 100755
--- a/chkcrontab_lib.py
+++ b/chkcrontab_lib.py
@@ -58,7 +58,8 @@ A brief description of each class and function:
                      cron line.
 
   Logging class to pretty-print output:
-    LogCounter: A logging class that provides a summary of warnings and errors.
+    LogCounter: A logging class that provides a summary of warnings and
+                errors.
 
   Putting it all together:
     CheckCrontab: Checks the a crontab file.
@@ -118,7 +119,8 @@ class FSM(object):
 
     if state not in self.states:
       self.states[state] = {}
-    self.states[state].update([(char, (action, next_state)) for char in chars])
+    self.states[state].update([(char, (action, next_state))
+                               for char in chars])
 
   def AddEndState(self, state, action):
     """Handle the end state of the FSM.
@@ -168,63 +170,75 @@ class FSM(object):
     return data_out
 
 
-def ActionTime(data_out, char):
+def action_time(data_out, char):
+  """Add a char to time."""
   data_out['time'] += char
 
 
-def ActionStar(data_out, char):
+def action_star(data_out, char):
+  """Add a char to time."""
   data_out['time'] = char
 
 
-def ActionDash(data_out, unused_char):
+def action_dash(data_out, unused_char):
+  """Move time to range, reset time."""
   data_out['range'] = data_out['time']
   data_out['time'] = ''
 
 
-def ActionStep(data_out, char):
+def action_step(data_out, char):
+  """Add a char to step."""
   data_out['step'] += char
 
 
-def ActionNoop(unused_data_out, unused_char):
+def action_noop(unused_data_out, unused_char):
+  """Do nothing."""
   pass
 
 
-def ActionTimeComma(data_out, unused_char=''):
+def action_time_comma(data_out, unused_char=''):
+  """Move time to cron_times, reset time."""
   data_out['cron_times'].append(CTTime(int(data_out['time'])))
   data_out['time'] = ''
 
 
-def ActionStarComma(data_out, unused_char=''):
+def action_star_comma(data_out, unused_char=''):
+  """Set cron_times, reset time."""
   data_out['cron_times'].append(CTStar())
   data_out['time'] = ''
 
 
-def ActionStarStepComma(data_out, unused_char=''):
+def action_star_step_comma(data_out, unused_char=''):
+  """Set cron_times, reset time & step."""
   data_out['cron_times'].append(CTStarStep(int(data_out['step'])))
   data_out['time'] = ''
   data_out['step'] = ''
 
 
-def ActionTextComma(data_out, unused_char=''):
+def action_text_comma(data_out, unused_char=''):
+  """Set cron_times from time, reset time."""
   data_out['cron_times'].append(CTText(data_out['time']))
   data_out['time'] = ''
 
 
-def ActionRangeComma(data_out, unused_char=''):
+def action_range_comma(data_out, unused_char=''):
+  """Set cron_times from range & time, reset range & time."""
   data_out['cron_times'].append(CTRange(int(data_out['range']),
                                         int(data_out['time'])))
   data_out['range'] = ''
   data_out['time'] = ''
 
 
-def ActionTextRangeComma(data_out, unused_char=''):
+def action_text_range_comma(data_out, unused_char=''):
+  """Set cron_times from range & time, reset range & time."""
   data_out['cron_times'].append(CTTextRange(data_out['range'],
                                             data_out['time']))
   data_out['range'] = ''
   data_out['time'] = ''
 
 
-def ActionRangeStepComma(data_out, unused_char=''):
+def action_range_step_comma(data_out, unused_char=''):
+  """Set cron_times from range, time & step, reset range, time & step."""
   data_out['cron_times'].append(CTRangeStep(int(data_out['range']),
                                             int(data_out['time']),
                                             int(data_out['step'])))
@@ -233,7 +247,8 @@ def ActionRangeStepComma(data_out, unused_char=''):
   data_out['step'] = ''
 
 
-def ActionTextRangeStepComma(data_out, unused_char=''):
+def action_text_range_step_comma(data_out, unused_char=''):
+  """Set cron_times from range, time & step, reset range, time & step."""
   data_out['cron_times'].append(CTTextRangeStep(data_out['range'],
                                                 data_out['time'],
                                                 int(data_out['step'])))
@@ -254,59 +269,61 @@ def InitCronFSM():
                   'cron_times': []}))
 
   # Case: *
-  fsm.AddTransition('*', 'start', ActionStar, 'star')
-  fsm.AddTransition('*', 'next', ActionStar, 'star')
-  fsm.AddEndState('star', ActionStarComma)
-  fsm.AddTransition(',', 'star', ActionStarComma, 'next')
+  fsm.AddTransition('*', 'start', action_star, 'star')
+  fsm.AddTransition('*', 'next', action_star, 'star')
+  fsm.AddEndState('star', action_star_comma)
+  fsm.AddTransition(',', 'star', action_star_comma, 'next')
   # Case: */<number>
-  fsm.AddTransition('/', 'star', ActionNoop, 'start_star_step')
-  fsm.AddTransition(string.digits, 'start_star_step', ActionStep, 'star_step')
-  fsm.AddTransition(string.digits, 'star_step', ActionStep, 'star_step')
-  fsm.AddEndState('star_step', ActionStarStepComma)
-  fsm.AddTransition(',', 'star_step', ActionStarStepComma, 'next')
+  fsm.AddTransition('/', 'star', action_noop, 'start_star_step')
+  fsm.AddTransition(string.digits, 'start_star_step', action_step,
+                    'star_step')
+  fsm.AddTransition(string.digits, 'star_step', action_step, 'star_step')
+  fsm.AddEndState('star_step', action_star_step_comma)
+  fsm.AddTransition(',', 'star_step', action_star_step_comma, 'next')
 
   # Case: <number>
-  fsm.AddTransition(string.digits, 'start', ActionTime, 'time')
-  fsm.AddTransition(string.digits, 'next', ActionTime, 'time')
-  fsm.AddTransition(string.digits, 'time', ActionTime, 'time')
-  fsm.AddEndState('time', ActionTimeComma)
-  fsm.AddTransition(',', 'time', ActionTimeComma, 'next')
+  fsm.AddTransition(string.digits, 'start', action_time, 'time')
+  fsm.AddTransition(string.digits, 'next', action_time, 'time')
+  fsm.AddTransition(string.digits, 'time', action_time, 'time')
+  fsm.AddEndState('time', action_time_comma)
+  fsm.AddTransition(',', 'time', action_time_comma, 'next')
   # Case: <number>-<number>
-  fsm.AddTransition('-', 'time', ActionDash, 'start_range')
-  fsm.AddTransition(string.digits, 'start_range', ActionTime, 'range')
-  fsm.AddTransition(string.digits, 'range', ActionTime, 'range')
-  fsm.AddEndState('range', ActionRangeComma)
-  fsm.AddTransition(',', 'range', ActionRangeComma, 'next')
+  fsm.AddTransition('-', 'time', action_dash, 'start_range')
+  fsm.AddTransition(string.digits, 'start_range', action_time, 'range')
+  fsm.AddTransition(string.digits, 'range', action_time, 'range')
+  fsm.AddEndState('range', action_range_comma)
+  fsm.AddTransition(',', 'range', action_range_comma, 'next')
   # Case: <number>-<number>/<number>
-  fsm.AddTransition('/', 'range', ActionNoop, 'start_range_step')
+  fsm.AddTransition('/', 'range', action_noop, 'start_range_step')
   fsm.AddTransition(string.digits, 'start_range_step',
-                    ActionStep, 'range_step')
-  fsm.AddTransition(string.digits, 'range_step', ActionStep, 'range_step')
-  fsm.AddEndState('range_step', ActionRangeStepComma)
-  fsm.AddTransition(',', 'range_step', ActionRangeStepComma, 'next')
+                    action_step, 'range_step')
+  fsm.AddTransition(string.digits, 'range_step', action_step, 'range_step')
+  fsm.AddEndState('range_step', action_range_step_comma)
+  fsm.AddTransition(',', 'range_step', action_range_step_comma, 'next')
 
   # Case: <text>
-  fsm.AddTransition(string.ascii_letters, 'start', ActionTime, 'text')
-  fsm.AddTransition(string.ascii_letters, 'next', ActionTime, 'text')
-  fsm.AddTransition(string.ascii_letters, 'text', ActionTime, 'text')
-  fsm.AddEndState('text', ActionTextComma)
-  fsm.AddTransition(',', 'text', ActionTextComma, 'next')
+  fsm.AddTransition(string.ascii_letters, 'start', action_time, 'text')
+  fsm.AddTransition(string.ascii_letters, 'next', action_time, 'text')
+  fsm.AddTransition(string.ascii_letters, 'text', action_time, 'text')
+  fsm.AddEndState('text', action_text_comma)
+  fsm.AddTransition(',', 'text', action_text_comma, 'next')
   # Case: <text>-<text>
-  fsm.AddTransition('-', 'text', ActionDash, 'start_text_range')
-  fsm.AddTransition(string.ascii_letters, 'start_text_range', ActionTime,
+  fsm.AddTransition('-', 'text', action_dash, 'start_text_range')
+  fsm.AddTransition(string.ascii_letters, 'start_text_range', action_time,
                     'text_range')
-  fsm.AddTransition(string.ascii_letters, 'text_range', ActionTime,
+  fsm.AddTransition(string.ascii_letters, 'text_range', action_time,
                     'text_range')
-  fsm.AddEndState('text_range', ActionTextRangeComma)
-  fsm.AddTransition(',', 'text_range', ActionTextRangeComma, 'next')
+  fsm.AddEndState('text_range', action_text_range_comma)
+  fsm.AddTransition(',', 'text_range', action_text_range_comma, 'next')
   # Case: <text>-<text>/<text>
-  fsm.AddTransition('/', 'text_range', ActionNoop, 'start_text_range_step')
-  fsm.AddTransition(string.digits, 'start_text_range_step', ActionStep,
+  fsm.AddTransition('/', 'text_range', action_noop, 'start_text_range_step')
+  fsm.AddTransition(string.digits, 'start_text_range_step', action_step,
                     'text_range_step')
-  fsm.AddTransition(string.digits, 'text_range_step', ActionStep,
+  fsm.AddTransition(string.digits, 'text_range_step', action_step,
                     'text_range_step')
-  fsm.AddEndState('text_range_step', ActionTextRangeStepComma)
-  fsm.AddTransition(',', 'text_range_step', ActionTextRangeStepComma, 'next')
+  fsm.AddEndState('text_range_step', action_text_range_step_comma)
+  fsm.AddTransition(',', 'text_range_step', action_text_range_step_comma,
+                    'next')
 
   return fsm
 
@@ -315,25 +332,33 @@ class CronTimeField(object):
   """CronTimeField superclass for various time specifiers in cron fields."""
 
   def __init__(self):
-    pass
+    self._text = None
+    self._kind = None
+    self._start = None
+    self._end = None
+    self._step = None
 
   def __str__(self):
     return self._text
 
   @property
   def kind(self):
+    """Kind field."""
     return self._kind
 
   @property
   def start(self):
+    """Start value of this field."""
     return self._start
 
   @property
   def end(self):
+    """End value of this field."""
     return self._end
 
   @property
   def step(self):
+    """Step for this field."""
     return self._step
 
   def CheckLowStep(self, diagnostics, cron_time_field):
@@ -497,6 +522,7 @@ class CTText(CronTimeField):
     self._text = '%s' % start_time
 
   def GetDiagnostics(self, cron_time_field):
+    """Checks for issues with a text field."""
     diagnostics = []
     self.CheckValidText(diagnostics, self._start, cron_time_field)
     return diagnostics
@@ -551,11 +577,14 @@ class CronTimeFieldLimit(object):
     self.min_time = min_time
     self.max_time = max_time
     self.valid_text = valid_text
+    self._name = None
 
   def _GetName(self):
+    """Return the name."""
     return self._name
 
   def _SetName(self, name):
+    """Set the name."""
     self._name = name
 
   name = property(_GetName, _SetName,
@@ -663,6 +692,9 @@ class CronLineTimeAction(object):
     self.user = user
     self.command = command
 
+  def _CheckTimeField(self, log):
+    pass
+
   def ValidateAndLog(self, log):
     """Validates an @ time spec line and logs any errors and warnings.
 
@@ -675,7 +707,8 @@ class CronLineTimeAction(object):
     if self.user in USER_WHITELIST:
       return
     elif len(self.user) > 31:
-      log.LineError(log.MSG_INVALID_USER, 'Username too long "%s"' % self.user)
+      log.LineError(log.MSG_INVALID_USER,
+                    'Username too long "%s"' % self.user)
     elif self.user.startswith('-'):
       log.LineError(log.MSG_INVALID_USER, 'Invalid username "%s"' % self.user)
     elif re.search(r'[\s!"#$%&\'()*+,/:;<=>?@[\\\]^`{|}~]', self.user):
@@ -811,6 +844,7 @@ class CronLineFactory(object):
 
 
 class LogMsgKindNotFound(Exception):
+  """Exception for broken log messages."""
   pass
 
 
diff --git a/setup.py b/setup.py
index 8bcadeff3ebb3ea8d55cab1c6b04c448533ee5e1..76b22c40f929d109717a27be545a1f6c8f281e00 100755
--- a/setup.py
+++ b/setup.py
@@ -64,9 +64,9 @@ class CleanCmd(Command):
 
   def run(self):
     # Configure for this project.
-    suffixes2del = [ 'MANIFEST', '.pyc', 'chkcrontabc' ]
-    dirs2del = [ './build', './dist' ]
-    dirs2ign = [ './.git' ]
+    suffixes2del = ['MANIFEST', '.pyc', 'chkcrontabc']
+    dirs2del = ['./build', './dist', './.tox', './.coverage']
+    dirs2ign = ['./.git']
     # End config.
     doomed = set()
     # Change to base dir.
@@ -162,7 +162,7 @@ if 'setuptools' not in dir():
 setup(
   cmdclass=cmdclass,
   name='chkcrontab',
-  version='1.3',
+  version='1.4a',
   url='http://code.google.com/p/chkcrontab',
   author='Kevin Lyda',
   author_email='lyda@google.com',