Add tests for config validator
This commit is contained in:
parent
a46f304c55
commit
a4d766034a
3 changed files with 242 additions and 7 deletions
|
@ -36,6 +36,10 @@ def test_input(config):
|
||||||
abs_input = os.path.abspath(config['input'])
|
abs_input = os.path.abspath(config['input'])
|
||||||
if len(glob.glob(abs_input)) == 0:
|
if len(glob.glob(abs_input)) == 0:
|
||||||
raise ConfigValidationException("No files found at {}".format(abs_input))
|
raise ConfigValidationException("No files found at {}".format(abs_input))
|
||||||
|
for file in glob.iglob(abs_input):
|
||||||
|
if not os.path.isfile(file):
|
||||||
|
raise ConfigValidationException("Input must be a glob of files")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def validate_bibliography(config):
|
def validate_bibliography(config):
|
||||||
|
@ -49,9 +53,8 @@ def validate_bibliography(config):
|
||||||
abs_bibliography = os.path.abspath(config['bibliography']['references'])
|
abs_bibliography = os.path.abspath(config['bibliography']['references'])
|
||||||
if not os.path.isfile(abs_bibliography):
|
if not os.path.isfile(abs_bibliography):
|
||||||
raise ConfigValidationException("Invalid bibliography path: '{}'".format(abs_bibliography))
|
raise ConfigValidationException("Invalid bibliography path: '{}'".format(abs_bibliography))
|
||||||
if 'csl' in config['bibliography']:
|
|
||||||
if not os.path.isfile(os.path.join(CSL_DIR, "{}.csl".format(config['bibliography']['csl']))):
|
if not os.path.isfile(os.path.join(CSL_DIR, "{}.csl".format(config['bibliography']['csl']))):
|
||||||
raise ConfigValidationException("Could not find CSL '{}'".format(config.bibliography.csl))
|
raise ConfigValidationException("Could not find CSL '{}'".format(config['bibliography']['csl']))
|
||||||
|
|
||||||
|
|
||||||
def validate_context(config):
|
def validate_context(config):
|
||||||
|
@ -63,11 +66,11 @@ def validate_context(config):
|
||||||
|
|
||||||
non_str_keys = [key for key in config['context'].keys() if type(key) != str]
|
non_str_keys = [key for key in config['context'].keys() if type(key) != str]
|
||||||
if non_str_keys:
|
if non_str_keys:
|
||||||
raise ConfigValidationException("Context keys must be strings. Non-strings: {}".format(", ".join(non_str_keys)))
|
raise ConfigValidationException("Context keys must be strings. Non-strings: {}".format(non_str_keys))
|
||||||
|
|
||||||
invalid_values = [value for value in config['context'].values() if type(value) in [list, dict]]
|
invalid_values = [value for value in config['context'].values() if type(value) in [list, dict]]
|
||||||
if invalid_values:
|
if invalid_values:
|
||||||
raise ConfigValidationException("Context keys must be plain. Invalid values: {}".format(", ".join(invalid_values)))
|
raise ConfigValidationException("Context keys must be plain. Invalid values: {}".format(invalid_values))
|
||||||
|
|
||||||
|
|
||||||
def validate_toc(config):
|
def validate_toc(config):
|
||||||
|
@ -92,7 +95,7 @@ def validate_submission_date(config):
|
||||||
try:
|
try:
|
||||||
parser.parse(config['submission_date'])
|
parser.parse(config['submission_date'])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ConfigValidationException("Invalid Submission Date format")
|
raise ConfigValidationException("Invalid Submission Date format {}".format(config['submission_date']))
|
||||||
|
|
||||||
|
|
||||||
def validate_config(config):
|
def validate_config(config):
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
|
||||||
python3 -m unittest -v
|
python3 -m unittest -v $@
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
from tests import BaseTestCase
|
from tests import BaseTestCase
|
||||||
from md_pdf.config import read, validate
|
from md_pdf.config import read, validate
|
||||||
from md_pdf.exceptions import ConfigValidationException
|
from md_pdf.exceptions import ConfigValidationException
|
||||||
|
from md_pdf.consts import CSL_DIR
|
||||||
|
from md_pdf.utils import remove_dir
|
||||||
import os
|
import os
|
||||||
|
import datetime
|
||||||
|
from unittest import skipIf
|
||||||
|
|
||||||
|
|
||||||
class ReadConfigTestCase(BaseTestCase):
|
class ReadConfigTestCase(BaseTestCase):
|
||||||
|
@ -13,3 +17,231 @@ class ReadConfigTestCase(BaseTestCase):
|
||||||
with self.assertRaises(ConfigValidationException):
|
with self.assertRaises(ConfigValidationException):
|
||||||
read.load_config(os.path.abspath('non-existant'))
|
read.load_config(os.path.abspath('non-existant'))
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigValidatorBaseTestCase(BaseTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.BASE_VALID_CONFIG = {
|
||||||
|
'title': 'test title',
|
||||||
|
'input': 'test-files/*.md',
|
||||||
|
'output_formats': [
|
||||||
|
'html', 'pdf'
|
||||||
|
],
|
||||||
|
'output_dir': 'out/',
|
||||||
|
|
||||||
|
}
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateSubmissionDateTestCase(ConfigValidatorBaseTestCase):
|
||||||
|
def test_transparent_to_datetime(self):
|
||||||
|
self.BASE_VALID_CONFIG['submission_date'] = datetime.datetime.now()
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_transparent_to_date(self):
|
||||||
|
self.BASE_VALID_CONFIG['submission_date'] = datetime.datetime.now().date()
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_transparent_to_time(self):
|
||||||
|
self.BASE_VALID_CONFIG['submission_date'] = datetime.datetime.now().time()
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_valid_date_format(self):
|
||||||
|
for date in [
|
||||||
|
'2017-01-01',
|
||||||
|
'01-01-2017',
|
||||||
|
'1st jan 2017',
|
||||||
|
'1 january 2017'
|
||||||
|
]:
|
||||||
|
self.BASE_VALID_CONFIG['submission_date'] = date
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_invalid_date_format(self):
|
||||||
|
for date in [
|
||||||
|
'nothing',
|
||||||
|
'31-02-2017',
|
||||||
|
'01-2017-01',
|
||||||
|
'1st smarch 2017'
|
||||||
|
]:
|
||||||
|
self.BASE_VALID_CONFIG['submission_date'] = date
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateWordcountTestCase(ConfigValidatorBaseTestCase):
|
||||||
|
def test_boolean_values_only(self):
|
||||||
|
self.BASE_VALID_CONFIG['show_word_count'] = True
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
self.BASE_VALID_CONFIG['show_word_count'] = False
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_invalid_values(self):
|
||||||
|
for value in [
|
||||||
|
'True',
|
||||||
|
'False',
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
]:
|
||||||
|
self.BASE_VALID_CONFIG['show_word_count'] = value
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateTOCTestCase(ConfigValidatorBaseTestCase):
|
||||||
|
def test_boolean_values_only(self):
|
||||||
|
self.BASE_VALID_CONFIG['toc'] = True
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
self.BASE_VALID_CONFIG['toc'] = False
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_invalid_values(self):
|
||||||
|
for value in [
|
||||||
|
'True',
|
||||||
|
'False',
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
]:
|
||||||
|
self.BASE_VALID_CONFIG['toc'] = value
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateContextTestCase(ConfigValidatorBaseTestCase):
|
||||||
|
def test_should_be_dict(self):
|
||||||
|
for value in [
|
||||||
|
[],
|
||||||
|
'dict',
|
||||||
|
1
|
||||||
|
]:
|
||||||
|
self.BASE_VALID_CONFIG['context'] = value
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
self.BASE_VALID_CONFIG['context'] = {}
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_non_string_keys(self):
|
||||||
|
self.BASE_VALID_CONFIG['context'] = {
|
||||||
|
1: 'test'
|
||||||
|
}
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_string_keys(self):
|
||||||
|
self.BASE_VALID_CONFIG['context'] = {
|
||||||
|
'1': 'test'
|
||||||
|
}
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_valid_values(self):
|
||||||
|
for value in [
|
||||||
|
'test',
|
||||||
|
1
|
||||||
|
]:
|
||||||
|
self.BASE_VALID_CONFIG['context'] = {
|
||||||
|
'test': value
|
||||||
|
}
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_invalid_values(self):
|
||||||
|
for value in [
|
||||||
|
[],
|
||||||
|
{}
|
||||||
|
]:
|
||||||
|
self.BASE_VALID_CONFIG['context'] = {
|
||||||
|
'test': value
|
||||||
|
}
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateBibliographyTestCase(ConfigValidatorBaseTestCase):
|
||||||
|
def test_contains_all_keys(self):
|
||||||
|
self.BASE_VALID_CONFIG['bibliography'] = {}
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
self.BASE_VALID_CONFIG['bibliography'] = {
|
||||||
|
'references': 'test'
|
||||||
|
}
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
self.BASE_VALID_CONFIG['bibliography'] = {
|
||||||
|
'csl': 'test'
|
||||||
|
}
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_valid_references(self):
|
||||||
|
self.BASE_VALID_CONFIG['bibliography'] = {
|
||||||
|
'references': 'non-existant',
|
||||||
|
'csl': 'chicago-author-date'
|
||||||
|
}
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
self.BASE_VALID_CONFIG['bibliography']['references'] = 'test-files/bib.yaml'
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
@skipIf(not os.path.isdir(CSL_DIR), 'Missing CSL Files')
|
||||||
|
def test_valid_csl(self):
|
||||||
|
self.BASE_VALID_CONFIG['bibliography'] = {
|
||||||
|
'references': 'test-files/bib.yaml',
|
||||||
|
'csl': 'nothing'
|
||||||
|
}
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
self.BASE_VALID_CONFIG['bibliography']['csl'] = 'chicago-author-date'
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateInputTestCase(ConfigValidatorBaseTestCase):
|
||||||
|
def test_no_matches(self):
|
||||||
|
self.BASE_VALID_CONFIG['input'] = 'test-files/*.mp4'
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_invalid_glob(self):
|
||||||
|
self.BASE_VALID_CONFIG['input'] = 'test-files/'
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateOutputTestCase(ConfigValidatorBaseTestCase):
|
||||||
|
def tearDown(self):
|
||||||
|
super().tearDown()
|
||||||
|
remove_dir('test-files/test')
|
||||||
|
|
||||||
|
def test_creates_output_dir(self):
|
||||||
|
self.assertFalse(os.path.isdir('test-files/test'))
|
||||||
|
self.BASE_VALID_CONFIG['output_dir'] = 'test-files/test'
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
self.assertTrue(os.path.isdir('test-files/test'))
|
||||||
|
|
||||||
|
def test_valid_output_formats(self):
|
||||||
|
for format in [
|
||||||
|
'html',
|
||||||
|
'pdf'
|
||||||
|
]:
|
||||||
|
self.BASE_VALID_CONFIG['output_formats'] = [format]
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_invalid_output_formats(self):
|
||||||
|
for format in [
|
||||||
|
'text',
|
||||||
|
'foo'
|
||||||
|
]:
|
||||||
|
self.BASE_VALID_CONFIG['output_formats'] = [format]
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
def test_part_invalid_format(self):
|
||||||
|
self.BASE_VALID_CONFIG['output_formats'] = ['html', 'foo']
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(self.BASE_VALID_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateRequiredKeysTestCase(ConfigValidatorBaseTestCase):
|
||||||
|
def test_required_keys(self):
|
||||||
|
for key in validate.REQUIRED_KEYS:
|
||||||
|
base_config = self.BASE_VALID_CONFIG.copy()
|
||||||
|
del base_config[key]
|
||||||
|
with self.assertRaises(ConfigValidationException):
|
||||||
|
validate.validate_config(base_config)
|
||||||
|
|
Reference in a new issue