Skip to content
Snippets Groups Projects

Add tests for function in util.py

Merged Kien Le requested to merge test-controller_code_util into master
+ 343
0
"""Test suite for functions defined in sohstationviewer.controller.util."""
import os
from unittest import TestCase
from unittest.mock import patch
from tempfile import TemporaryDirectory, NamedTemporaryFile
import string
from sohstationviewer.controller.util import (
validateFile,
getDirSize,
getTime6,
getTime6_2y,
getTime6_4y,
getTime4,
getVal,
rtnPattern,
fmti
)
TEST_DATA_DIR = os.path.realpath(os.path.join(
os.path.dirname(os.path.realpath(__file__)),
os.pardir,
'test_data',
))
class TestGetTime(TestCase):
"""Test suite for getTime6, getTime6_2y, getTime6_4y, and getTime4."""
def setUp(self):
"""Set up text fixtures."""
self.time6_2y = '01:251:09:41:35:656'
self.time6_4y = '2001:251:09:41:35:656'
self.time4_day_1 = '1:09:41:35'
self.time4 = '251:09:41:35'
@patch('sohstationviewer.controller.util.getTime6_4y')
@patch('sohstationviewer.controller.util.getTime6_2y')
def test_get_time6(self, mock_2y, mock_4y):
"""
Test getTime6 - check that getTime6 delegates work to the appropriate
helper function depending on the input.
"""
with self.subTest('test_2_digit_year'):
getTime6(self.time6_2y)
self.assertTrue(mock_2y.called)
self.assertFalse(mock_4y.called)
mock_2y.reset_mock()
mock_4y.reset_mock()
with self.subTest('test_4_digit_year'):
getTime6(self.time6_4y)
self.assertTrue(mock_4y.called)
self.assertFalse(mock_2y.called)
def test_get_time6_invalid_input(self):
"""Test getTime6 - the input is not one of the expected formats."""
with self.subTest('test_input_contains_colon'):
bad_inputs = [':523:531:', 'fs:523:531:', 'towe:523:531:']
for input_str in bad_inputs:
with self.assertRaises(ValueError):
getTime6(input_str)
with self.subTest('test_input_does_not_contain_colon'):
input_str = 'fq31dqrt63'
with self.assertRaises(ValueError):
getTime6(input_str)
def test_get_time6_2y(self):
"""Test getTime6_2y."""
epoch_time, year = getTime6_2y(self.time6_2y)
self.assertAlmostEqual(epoch_time, 999942095.656)
self.assertEqual(year, 2001)
def test_get_time6_4y(self):
"""Test getTime6_4y."""
epoch_time, year = getTime6_4y(self.time6_4y)
self.assertAlmostEqual(epoch_time, 999942095.656)
self.assertEqual(year, 2001)
def test_get_time4_year_added(self):
"""Test getTime4 - a year has been added."""
year = 2001
year_added = True
with self.subTest('test_first_day_of_year'):
epoch_time, ret_year, ret_year_added = (
getTime4(self.time4_day_1, year, year_added)
)
self.assertEqual(epoch_time, 978342095)
self.assertEqual(ret_year, year)
self.assertTrue(ret_year_added)
with self.subTest('test_other_days'):
epoch_time, ret_year, ret_year_added = (
getTime4(self.time4, year, year_added)
)
self.assertEqual(epoch_time, 999942095)
self.assertEqual(ret_year, year)
self.assertTrue(ret_year_added)
def test_get_time4_year_not_added(self):
"""Test getTime4 - a year has not been added."""
year = 2001
year_added = False
with self.subTest('test_first_day_of_year'):
epoch_time, ret_year, ret_year_added = (
getTime4(self.time4_day_1, year, year_added)
)
self.assertEqual(epoch_time, 1009878095)
self.assertEqual(ret_year, year + 1)
self.assertTrue(ret_year_added)
with self.subTest('test_other_days'):
epoch_time, ret_year, ret_year_added = (
getTime4(self.time4, year, year_added)
)
self.assertEqual(epoch_time, 999942095)
self.assertEqual(ret_year, year)
self.assertFalse(ret_year_added)
class TestValidateFile(TestCase):
"""Test suite for validateFile."""
def test_valid_file(self):
"""
Test basic functionality of validateFile - given file exists and is not
an info file.
"""
with NamedTemporaryFile() as valid_file:
self.assertTrue(
validateFile(valid_file.name,
os.path.basename(valid_file.name))
)
def test_info_file(self):
"""
Test basic functionality of validateFile - given file exists and is an
info file.
"""
with self.subTest('test_dot_DS_Store'):
with TemporaryDirectory() as temp_dir:
# There are two ways to create a temporary file with a
# custom name. The first way is to create a temporary
# directory, then create a file in that directory. When the
# temporary directory is deleted, the file is also deleted.
# This automatic deletion effectively makes the file we created
# a temporary file.
# The second way is to create a temporary file and rename it
# to the name we want. Then, we need to rename the file back
# to its original name once we are done. This renaming is
# needed because temporary file deletes itself based on its
# name attribute, which is not changed in the first
# renaming. While the second way makes it explicit that we
# only want a temporary file, it might not be clear why the
# second renaming is needed. In order to cause less
# confusion in the code, we create this temporary file the
# first way.
ds_store_path = os.path.join(temp_dir, '.DS_Store')
with open(ds_store_path, 'w+') as ds_store_file:
self.assertFalse(
validateFile(ds_store_path,
os.path.basename(ds_store_file.name))
)
with self.subTest('test_dot_underscore'):
with NamedTemporaryFile(prefix='._') as info_file:
self.assertFalse(
validateFile(info_file.name,
os.path.basename(info_file.name))
)
def test_file_does_not_exist(self):
"""
Test basic functionality of validateFile - given file does not exist.
"""
empty_name_file = ''
self.assertFalse(validateFile(empty_name_file, empty_name_file))
not_exist_file = 'file_does_not_exist'
self.assertFalse(validateFile(not_exist_file, not_exist_file))
class TestGetDirSize(TestCase):
"""Test suite for getDirSize."""
def test_files_have_size_zero(self):
"""Test getDirSize - all files in the given directory has size zero."""
expected_file_count = 10
with TemporaryDirectory() as directory:
files = []
for i in range(expected_file_count):
files.append(NamedTemporaryFile(dir=directory))
dir_size, dir_file_count = getDirSize(directory)
self.assertEqual(dir_size, 0)
self.assertEqual(dir_file_count, expected_file_count)
# Explicitly clean up the temporary files. If we don't do this,
# the temporary directory will clean up itself and delete the
# temporary files. Then, when the function returns, the references
# to these temporary files will attempt to clean up the files. This
# leads to exceptions being raised because the files being cleaned
# up does not exist any more.
files = [file.close() for file in files]
def test_files_have_size_greater_than_zero(self):
"""
Test getDirSize - all files in the given directory have a size greater
than zero.
"""
expected_file_count = 10
size_one_file = 10
# Each byte character is 1 byte, so we can obtain a byte string of n
# bytes by creating a byte string with n characters.
byte_to_write = b'a' * size_one_file
temp_dir = TemporaryDirectory()
with TemporaryDirectory(dir=temp_dir.name) as directory:
files = []
for i in range(expected_file_count):
temp_file = NamedTemporaryFile(dir=directory)
temp_file.write(byte_to_write)
# Writing to file is not done until requested so we need to
# explicitly tell Python to finish the write. Otherwise, the
# size of the file on disk will stay 0.
temp_file.flush()
files.append(temp_file)
dir_size, dir_file_count = getDirSize(temp_dir.name)
self.assertEqual(dir_size, size_one_file * expected_file_count)
self.assertEqual(dir_file_count, expected_file_count)
# Explicitly clean up the temporary files. If we don't do this,
# the temporary directory will clean up itself and delete the
# temporary files. Then, when the function returns, the references
# to these temporary files will attempt to clean up the files. This
# leads to exceptions being raised because the files being cleaned
# up does not exist any more.
files = [file.close() for file in files]
def test_nested_folder_structure(self):
"""
Test getDirSize - the given directory contains nested directories.
"""
test_folder = os.path.join(TEST_DATA_DIR, 'Pegasus-sample')
dir_size, dir_file_count = getDirSize(test_folder)
self.assertEqual(dir_size, 7909115)
self.assertEqual(dir_file_count, 8)
def test_empty_directory(self):
"""Test getDirSize - the given directory contains no file."""
with TemporaryDirectory() as temp_dir:
dir_size, dir_file_count = getDirSize(temp_dir)
self.assertEqual(dir_size, 0)
self.assertEqual(dir_file_count, 0)
def test_directory_does_not_exist(self):
"""Test getDirSize - the given directory does not exist."""
empty_name_dir = ''
dir_size, dir_file_count = getDirSize(empty_name_dir)
self.assertEqual(dir_size, 0)
self.assertEqual(dir_file_count, 0)
non_existent_dir = 'directory does not exist'
dir_size, dir_file_count = getDirSize(non_existent_dir)
self.assertEqual(dir_size, 0)
self.assertEqual(dir_file_count, 0)
class TestRtnPattern(TestCase):
"""Test suite for rtnPattern."""
def test_no_upper(self):
"""Test rtnPattern - characters are not converted to uppercase."""
with self.subTest('test_digit'):
digits = '123456789'
self.assertEqual(rtnPattern(digits), '0' * len(digits))
with self.subTest('test_lowercase'):
lowercase_chars = string.ascii_lowercase
self.assertEqual(rtnPattern(lowercase_chars),
'a' * len(lowercase_chars))
with self.subTest('test_uppercase'):
uppercase_chars = string.ascii_uppercase
self.assertEqual(rtnPattern(uppercase_chars),
'A' * len(uppercase_chars))
def test_with_upper(self):
"""Test rtnPattern - all characters are converted to uppercase."""
lowercase_chars = string.ascii_lowercase
self.assertEqual(rtnPattern(lowercase_chars, upper=True),
'A' * len(lowercase_chars))
class TestGetVal(TestCase):
"""Test suite for getVal."""
def test_normal_case(self):
"""Test getVal - the input is of an expected value."""
# formatter:off
test_name_to_test_map = {
'test_with_decimal_point': ('60.3V', 60.3),
'test_no_decimal_point': ('15V', 15.0),
'test_with_plus_sign': ('+35.5V', 35.5),
'test_with_negative_sign': ('-35.2V', -35.2),
'test_multiple_decimal_digits': ('52.523V', 52.5),
'test_no_decimal_digit': ('12.V', 12.0),
}
# formatter:on
for test_name, inout_pair in test_name_to_test_map.items():
with self.subTest(test_name):
self.assertEqual(getVal(inout_pair[0]), inout_pair[1])
def test_positive_negative_sign_in_front(self):
"""
Test rtnPattern - the input has both a positive sign and a negative
sign in the front.
"""
with self.assertRaises(ValueError):
getVal('+-1.0V')
def test_bad_input(self):
"""Test rtnPattern - the input has a value that is not expected."""
with self.assertRaises(AttributeError):
getVal('')
class TestFmti(TestCase):
"""Test suite for fmti."""
def test_absolute_value_below_1000(self):
"""
Test fmti - the input is greater than -1000 but smaller than 1000.
"""
with self.subTest('test_positive'):
val = 52.521
self.assertEqual(fmti(val), '52')
with self.subTest('test_negative'):
val = -232.42
self.assertEqual(fmti(val), '-232')
def test_absolute_value_above_1000(self):
"""
Test fmti - the input is greater than 1000 or smaller than -1000.
"""
with self.subTest('test_positive'):
val = 136235646.215151
expected = '136,235,646'
self.assertEqual(fmti(val), expected)
with self.subTest('test_negative'):
val = -62362.32523
expected = '-62,362'
self.assertEqual(fmti(val), expected)
Loading