update extractor-unittest capabilities
- "count" can now be a string defining a comparison in the form of
'<operator> <value>', for example: '> 12' or '!= 1'. If its value
is not a string, it is assumed to be a concrete integer as before.
- "keyword" can now be a dictionary defining tests for individual keys.
These tests can either be a type, a concrete value or a regex
starting with "re:". Dictionaries can be stacked inside each other.
Optional keys can be indicated with a "?" before its name.
For example:
"keyword:" {
"image_id": int,
"gallery_id", 123,
"name": "re:pattern",
"user": {
"id": 321,
},
"?optional": None,
}
This commit is contained in:
@@ -289,7 +289,8 @@ class TestJob(DownloadJob):
|
|||||||
def __init__(self, url, parent=None, content=False):
|
def __init__(self, url, parent=None, content=False):
|
||||||
DownloadJob.__init__(self, url, parent)
|
DownloadJob.__init__(self, url, parent)
|
||||||
self.content = content
|
self.content = content
|
||||||
self.urllist = []
|
self.list_url = []
|
||||||
|
self.list_keyword = []
|
||||||
self.hash_url = hashlib.sha1()
|
self.hash_url = hashlib.sha1()
|
||||||
self.hash_keyword = hashlib.sha1()
|
self.hash_keyword = hashlib.sha1()
|
||||||
self.hash_content = hashlib.sha1()
|
self.hash_content = hashlib.sha1()
|
||||||
@@ -306,7 +307,7 @@ class TestJob(DownloadJob):
|
|||||||
self.update_content(url)
|
self.update_content(url)
|
||||||
|
|
||||||
def handle_directory(self, keywords):
|
def handle_directory(self, keywords):
|
||||||
self.update_keyword(keywords)
|
self.update_keyword(keywords, False)
|
||||||
|
|
||||||
def handle_queue(self, url, keywords):
|
def handle_queue(self, url, keywords):
|
||||||
self.update_url(url)
|
self.update_url(url)
|
||||||
@@ -314,14 +315,15 @@ class TestJob(DownloadJob):
|
|||||||
|
|
||||||
def update_url(self, url):
|
def update_url(self, url):
|
||||||
"""Update the URL hash"""
|
"""Update the URL hash"""
|
||||||
self.urllist.append(url)
|
self.list_url.append(url)
|
||||||
self.hash_url.update(url.encode())
|
self.hash_url.update(url.encode())
|
||||||
|
|
||||||
def update_keyword(self, kwdict):
|
def update_keyword(self, kwdict, to_list=True):
|
||||||
"""Update the keyword hash"""
|
"""Update the keyword hash"""
|
||||||
|
if to_list:
|
||||||
|
self.list_keyword.append(kwdict.copy())
|
||||||
self.hash_keyword.update(
|
self.hash_keyword.update(
|
||||||
json.dumps(kwdict, sort_keys=True).encode()
|
json.dumps(kwdict, sort_keys=True).encode())
|
||||||
)
|
|
||||||
|
|
||||||
def update_content(self, url):
|
def update_content(self, url):
|
||||||
"""Update the content hash"""
|
"""Update the content hash"""
|
||||||
|
|||||||
@@ -12,6 +12,16 @@ import unittest
|
|||||||
from gallery_dl import extractor, job, config, exception
|
from gallery_dl import extractor, job, config, exception
|
||||||
|
|
||||||
|
|
||||||
|
SKIP = {
|
||||||
|
# don't work on travis-ci
|
||||||
|
"exhentai", "kissmanga", "mangafox", "dynastyscans", "nijie",
|
||||||
|
"archivedmoe", "archiveofsins", "thebarchive",
|
||||||
|
|
||||||
|
# temporary issues
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TestExtractors(unittest.TestCase):
|
class TestExtractors(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -51,65 +61,93 @@ class TestExtractors(unittest.TestCase):
|
|||||||
try:
|
try:
|
||||||
if 500 <= exc.args[0].response.status_code < 600:
|
if 500 <= exc.args[0].response.status_code < 600:
|
||||||
self.skipTest(exc)
|
self.skipTest(exc)
|
||||||
except AttributeError as e:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
raise
|
raise
|
||||||
|
|
||||||
if "url" in result:
|
if "url" in result:
|
||||||
self.assertEqual(result["url"], tjob.hash_url.hexdigest())
|
self.assertEqual(result["url"], tjob.hash_url.hexdigest())
|
||||||
if "keyword" in result:
|
|
||||||
self.assertEqual(result["keyword"], tjob.hash_keyword.hexdigest())
|
|
||||||
if "content" in result:
|
if "content" in result:
|
||||||
self.assertEqual(result["content"], tjob.hash_content.hexdigest())
|
self.assertEqual(result["content"], tjob.hash_content.hexdigest())
|
||||||
|
|
||||||
|
if "keyword" in result:
|
||||||
|
keyword = result["keyword"]
|
||||||
|
if isinstance(keyword, dict):
|
||||||
|
for kwdict in tjob.list_keyword:
|
||||||
|
self._test_kwdict(kwdict, keyword)
|
||||||
|
else: # assume SHA1 hash
|
||||||
|
self.assertEqual(keyword, tjob.hash_keyword.hexdigest())
|
||||||
|
|
||||||
if "count" in result:
|
if "count" in result:
|
||||||
self.assertEqual(len(tjob.urllist), int(result["count"]))
|
count = result["count"]
|
||||||
|
if isinstance(count, str):
|
||||||
|
self.assertRegex(count, r"^ *(==|!=|<|<=|>|>=) *\d+ *$")
|
||||||
|
expr = "{} {}".format(len(tjob.list_url), count)
|
||||||
|
self.assertTrue(eval(expr), msg=expr)
|
||||||
|
else: # assume integer
|
||||||
|
self.assertEqual(len(tjob.list_url), count)
|
||||||
|
|
||||||
if "pattern" in result:
|
if "pattern" in result:
|
||||||
for url in tjob.urllist:
|
for url in tjob.list_url:
|
||||||
self.assertRegex(url, result["pattern"])
|
self.assertRegex(url, result["pattern"])
|
||||||
|
|
||||||
|
def _test_kwdict(self, kwdict, tests):
|
||||||
|
for key, test in tests.items():
|
||||||
|
if key.startswith("?"):
|
||||||
|
key = key[1:]
|
||||||
|
if key not in kwdict:
|
||||||
|
continue
|
||||||
|
self.assertIn(key, kwdict)
|
||||||
|
value = kwdict[key]
|
||||||
|
|
||||||
# dynamically generate tests
|
if isinstance(test, dict):
|
||||||
def _generate_test(extr, tcase):
|
self._test_kwdict(kwdict[key], test)
|
||||||
def test(self):
|
continue
|
||||||
url, result = tcase
|
elif isinstance(test, type):
|
||||||
print("\n", url, sep="")
|
self.assertIsInstance(value, test)
|
||||||
self._run_test(extr, url, result)
|
elif isinstance(test, str) and value.startswith("re:"):
|
||||||
return test
|
self.assertRegex(value, test[3:])
|
||||||
|
else:
|
||||||
|
self.assertEqual(value, test)
|
||||||
|
|
||||||
|
|
||||||
skip = [
|
def generate_tests():
|
||||||
# don't work on travis-ci
|
"""Dynamically generate extractor unittests"""
|
||||||
"exhentai", "kissmanga", "mangafox", "dynastyscans", "nijie",
|
def _generate_test(extr, tcase):
|
||||||
"archivedmoe", "archiveofsins", "thebarchive",
|
def test(self):
|
||||||
# temporary issues
|
url, result = tcase
|
||||||
"mangapark",
|
print("\n", url, sep="")
|
||||||
]
|
self._run_test(extr, url, result)
|
||||||
# enable selective testing for direct calls
|
return test
|
||||||
if __name__ == '__main__' and len(sys.argv) > 1:
|
|
||||||
if sys.argv[1].lower() == "all":
|
# enable selective testing for direct calls
|
||||||
extractors = extractor.extractors()
|
if __name__ == '__main__' and len(sys.argv) > 1:
|
||||||
|
if sys.argv[1].lower() == "all":
|
||||||
|
extractors = extractor.extractors()
|
||||||
|
else:
|
||||||
|
extractors = [
|
||||||
|
extr for extr in extractor.extractors()
|
||||||
|
if extr.category in sys.argv or
|
||||||
|
hasattr(extr, "basecategory") and extr.basecategory in sys.argv
|
||||||
|
]
|
||||||
|
del sys.argv[1:]
|
||||||
else:
|
else:
|
||||||
extractors = [
|
extractors = [
|
||||||
extr for extr in extractor.extractors()
|
extr for extr in extractor.extractors()
|
||||||
if extr.category in sys.argv or
|
if extr.category not in SKIP
|
||||||
hasattr(extr, "basecategory") and extr.basecategory in sys.argv
|
|
||||||
]
|
]
|
||||||
del sys.argv[1:]
|
|
||||||
else:
|
|
||||||
extractors = [
|
|
||||||
extr for extr in extractor.extractors()
|
|
||||||
if extr.category not in skip
|
|
||||||
]
|
|
||||||
|
|
||||||
|
for extr in extractors:
|
||||||
for extr in extractors:
|
if not hasattr(extr, "test") or not extr.test:
|
||||||
if hasattr(extr, "test") and extr.test:
|
continue
|
||||||
name = "test_" + extr.__name__ + "_"
|
name = "test_" + extr.__name__ + "_"
|
||||||
for num, tcase in enumerate(extr.test, 1):
|
for num, tcase in enumerate(extr.test, 1):
|
||||||
test = _generate_test(extr, tcase)
|
test = _generate_test(extr, tcase)
|
||||||
test.__name__ = name + str(num)
|
test.__name__ = name + str(num)
|
||||||
setattr(TestExtractors, test.__name__, test)
|
setattr(TestExtractors, test.__name__, test)
|
||||||
del test
|
|
||||||
|
|
||||||
|
|
||||||
|
generate_tests()
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(warnings='ignore')
|
unittest.main(warnings='ignore')
|
||||||
|
|||||||
Reference in New Issue
Block a user