Skip to content

Commit

Permalink
Added some testing.
Browse files Browse the repository at this point in the history
This just calls all functions in turn, both normally and with a simulated
broken ctypes, and makes sure they all return None or the expected return
type.
I should probably make sure all uptime helpers actually return a float
later, because I think there's at least one int in there somewhere.

Python's unittest is pretty rough.
  • Loading branch information
Cairnarvon committed Feb 7, 2013
1 parent 57fd96f commit 121d283
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ all:
@echo "Targets:"
@echo " pypi Build distributions and upload them to PyPI."
@echo " uptime.zip Build docs and zip them for manual upload to PyPI."
@echo " tests Run the unit tests."
@echo " clean Clear out temporary cruft."

.PHONY: pypi
Expand All @@ -13,6 +14,14 @@ uptime.zip: doc/index.rst doc/conf.py
cd doc; $(MAKE) clean html
cd doc/_build/html; zip -r ../../../uptime.zip *

.PHONY: tests
tests:
@python --version
@python tests/uptime_tests.py
@echo
@python3 --version
@python3 tests/uptime_tests.py

.PHONY: clean
clean:
cd doc; $(MAKE) clean
Expand Down
121 changes: 121 additions & 0 deletions tests/uptime_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env python
# coding: utf8

import imp
import sys
import time
import unittest

sys.path.insert(0, '.')

import src as uptime


boottime_helpers = [f for f in vars(uptime) if f.startswith('_boottime_')]
uptime_helpers = [f for f in vars(uptime) if f.startswith('_uptime_')]


class NormalTest(unittest.TestCase):
"""
This class just calls each of the functions normally and ensures they don't
do dumb things like throw exceptions or return complex numbers.
"""
def tearDown(self):
"""
__boottime affects how boottime() and its helpers work, and it may be
set as a side-effect by any function. To be on the safe side, just
reload the whole module every time.
"""
imp.reload(uptime)

def basic_test(self, func, rettype):
"""
Calls a given function and checks if it returns None or something of
type rettype.
"""
ret = func()
self.assertTrue(ret is None or isinstance(ret, rettype))

def __getattr__(self, name):
# I really don't feel like writing and maintaining over a dozen
# essentially identical methods, and if there's a cleaner way to do
# this, I couldn't find it in the unittest docs.
if name.startswith('test_'):
func = name[5:]
if func == 'uptime' or func in uptime_helpers:
rettype = float
elif func == 'boottime' or func in boottime_helpers:
rettype = time.struct_time
else:
raise AttributeError()
return lambda: self.basic_test(getattr(uptime, func), rettype)
else:
return unittest.TestCase.__getattr__(self, name)

class BrokenCtypesTest(NormalTest):
"""
It's ridiculous how many platforms don't have ctypes. This class simulates
that.
"""
def setUpClass(self):
uptime.ctypes = None
delattr(uptime, 'struct')
delattr(uptime, 'os')


def run_suite(suite):
"""
unittest is basically a disaster, so let's do this ourselves.
"""
sys.stdout.write('Running %d tests... \n' % tests.countTestCases())

res = unittest.TestResult()
suite.run(res)

if res.wasSuccessful():
sys.stdout.write('Finished without errors.\n')
return

sys.stdout.write('\n')
for problems, kind in ((res.errors, 'error'),
(res.failures, 'failure')):
if len(problems):
head = '%d %s%s' % (len(problems),
kind,
's' if len(problems) != 1 else '')
sys.stdout.write('\033[1;31m%s\n%s\033[0m\n' %
(head, '⎻' * len(head)))

for problem in problems:
func = problem[0]._testMethodName[5:]
environ = ' (broken ctypes)' if isinstance(problem[0],
BrokenCtypesTest) \
else ''
sys.stdout.write(
'• \033[1m%s%s\033[0m failed with message:\n\n%s\n\n' %
(func, environ, '\n'.join(map(lambda s: ' ' + s,
problem[1].splitlines())))
)

sys.stdout.write('%d tests completed successfully.\n' %
(res.testsRun - len(res.failures) - len(res.errors)))


if __name__ == '__main__':
tests = unittest.TestSuite()

# uptime tests
tests.addTests([NormalTest('test_uptime'),
BrokenCtypesTest('test_uptime')])
for helper in uptime_helpers:
tests.addTests([NormalTest('test_%s' % helper),
BrokenCtypesTest('test_%s' % helper)])

# boottime tests
tests.addTests([NormalTest('test_boottime'),
BrokenCtypesTest('test_boottime')])
for helper in boottime_helpers:
tests.addTests([NormalTest('test_%s' % helper),
BrokenCtypesTest('test_%s' % helper)])

run_suite(tests)

0 comments on commit 121d283

Please sign in to comment.