Test framework code - mikec964/chelmbigstock GitHub Wiki
The best explanation I've found for this is on StackOverFlow. It's flippin' genius.
Our code is set up like this:
/league
/data
/league
__init__.py # makes league a package
match.py # this is a module
/test
__init__.py # makes test a package
test_match.py
The challenge is to enable the code in test_match.py to be able to call methods in match.py.
The code in test_match.py will import match.py as a module. Therefore, you must:
- Include
__init__.py
in the directory to make the directory into a package - Test names must be separated by an underscore, not a dash. Really.
Sample Test Program
file: test_stock.py
#!/usr/bin/env python3
import unittest
# These three lines enable you to run this from within the Tests directory
import os
import sys
sys.path.append(os.path.abspath('..'))
import league.match as match
class Test_read_players(unittest.TestCase):
def test_loaded_some_players(self):
players = []
players = match.read_players()
self.assertNotEqual(players, [])
class Test_match_players(unittest.TestCase):
def test_matched_players(self):
pass
if __name__ == '__main__':
unittest.main()
You can run this test by executing it directly:
$ cd league/test
$ python3 -m unittest test_match # leave off the .py extension
You can run all tests in this directory with:
$ cd league/league
$ python -m unittest discover
You can go up a level and run all the tests with the same command:
$ cd league
$ python -m unittest discover
Note This requires:
- The test directory is named 'test' (not tests)
- The test modules are named test*.py
- The test modules use underscores, not dashes
I prefer a tests
directory and to name the tests something_tests.py so it is easier to read the list in the directory.
$ cd league
$ python -m unittest discover -s tests -p '*tests.py'
I've created some aliases in .bashrc:
alias pytest='python -m unittest'
alias pytests='python -m unittest discover -s tests -p "*tests.py"'
alias py3test='python3 -m unittest'
alias py3tests='python3 -m unittest discover -s tests -p "*tests.py"'
Sample Program
If the program method or function reads data from a file, then when you import that method from your test program, it may not be able to find the file. Here's another solution from StackOverflow
WRONG:
filepath = '../data/players.txt'
with open('filepath', newline='') as csvfile:
player_reader = csv.reader(csvfile, delimiter=' ')
The code below solves two problems:
- It ensures the path to the data directory and file are relative to the module, not the calling program
- It uses 'join' instead of '/', so the program works across Windows, Linux, and Mac OS.
RIGHT:
datadir = 'data'
filename = 'players.csv'
# Use dirname(__file__) so this runs even when called from ../tests
filepath = os.path.join(os.path.dirname(__file__), os.pardir, datadir, filename)
with open(filepath, newline='') as csvfile:
player_reader = csv.reader(csvfile, delimiter=' ')
#!/usr/bin/env python3
import os
import sys
import csv
def read_players():
# read ../data/players.csv
datadir = 'data'
filename = 'players.csv'
# Use dirname(__file__) so this runs even when called from ./tests
filepath = os.path.join(os.path.dirname(__file__), os.pardir, datadir, filename)
players = []
with open(filepath, newline='') as csvfile:
player_reader = csv.reader(csvfile, delimiter=' ')
for row in player_reader:
players.append(row)
return players
def match_players():
# create combinations
pass
def print_matches():
pass
if __name__ == "__main__":
read_players()
match_players()
print_matches()