Skip to content

Commit 9337b00

Browse files
committed
Use py.test to generate tests from the data files themselves.
1 parent 9a10a4c commit 9337b00

File tree

6 files changed

+121
-103
lines changed

6 files changed

+121
-103
lines changed

Diff for: .pytest.expect

14.1 KB
Binary file not shown.

Diff for: html5lib/tests/conftest.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import os.path
2+
3+
from .tree_construction import TreeConstructionFile
4+
5+
_dir = os.path.abspath(os.path.dirname(__file__))
6+
_testdata = os.path.join(_dir, "testdata")
7+
_tree_construction = os.path.join(_testdata, "tree-construction")
8+
9+
10+
def pytest_collectstart():
11+
"""check to see if the git submodule has been init'd"""
12+
pass
13+
14+
15+
def pytest_collect_file(path, parent):
16+
dir = os.path.abspath(path.dirname)
17+
if dir == _tree_construction:
18+
if path.basename == "template.dat":
19+
return
20+
if path.ext == ".dat":
21+
return TreeConstructionFile(path, parent)

Diff for: html5lib/tests/support.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,18 @@
2727
try:
2828
import xml.etree.cElementTree as cElementTree
2929
except ImportError:
30-
pass
30+
treeTypes['cElementTree'] = None
3131
else:
3232
# On Python 3.3 and above cElementTree is an alias, don't run them twice.
33-
if cElementTree.Element is not ElementTree.Element:
33+
if cElementTree.Element is ElementTree.Element:
34+
treeTypes['cElementTree'] = None
35+
else:
3436
treeTypes['cElementTree'] = treebuilders.getTreeBuilder("etree", cElementTree, fullTree=True)
3537

3638
try:
3739
import lxml.etree as lxml # flake8: noqa
3840
except ImportError:
39-
pass
41+
treeTypes['lxml'] = None
4042
else:
4143
treeTypes['lxml'] = treebuilders.getTreeBuilder("lxml")
4244

@@ -63,9 +65,6 @@ def __init__(self, filename, newTestHeading="data", encoding="utf8"):
6365
self.encoding = encoding
6466
self.newTestHeading = newTestHeading
6567

66-
def __del__(self):
67-
self.f.close()
68-
6968
def __iter__(self):
7069
data = DefaultDict(None)
7170
key = None

Diff for: html5lib/tests/test_parser.py

-96
This file was deleted.

Diff for: html5lib/tests/tree_construction.py

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
from __future__ import absolute_import, division, unicode_literals
2+
3+
import warnings
4+
import re
5+
6+
import pytest
7+
8+
from .support import TestData, convert, convertExpected, treeTypes
9+
from html5lib import html5parser, constants
10+
11+
12+
class TreeConstructionFile(pytest.File):
13+
def collect(self):
14+
tests = TestData(str(self.fspath), "data")
15+
for i, test in enumerate(tests):
16+
for treeName, treeClass in sorted(treeTypes.items()):
17+
for namespaceHTMLElements in (True, False):
18+
if namespaceHTMLElements:
19+
nodeid = "%d::%s::namespaced" % (i, treeName)
20+
else:
21+
nodeid = "%d::%s::void-namespace" % (i, treeName)
22+
item = ParserTest(nodeid, self,
23+
test, treeClass, namespaceHTMLElements)
24+
item.add_marker(getattr(pytest.mark, treeName))
25+
if namespaceHTMLElements:
26+
item.add_marker(pytest.mark.namespaced)
27+
if treeClass is None:
28+
item.add_marker(pytest.mark.skipif(True, reason="Treebuilder not loaded"))
29+
yield item
30+
31+
32+
def convertTreeDump(data):
33+
return "\n".join(convert(3)(data).split("\n")[1:])
34+
35+
namespaceExpected = re.compile(r"^(\s*)<(\S+)>", re.M).sub
36+
37+
38+
class ParserTest(pytest.Item):
39+
def __init__(self, name, parent, test, treeClass, namespaceHTMLElements):
40+
super(ParserTest, self).__init__(name, parent)
41+
self.obj = lambda: 1 # this is to hack around skipif needing a function!
42+
self.test = test
43+
self.treeClass = treeClass
44+
self.namespaceHTMLElements = namespaceHTMLElements
45+
46+
def runtest(self):
47+
p = html5parser.HTMLParser(tree=self.treeClass,
48+
namespaceHTMLElements=self.namespaceHTMLElements)
49+
50+
input = self.test['data']
51+
fragmentContainer = self.test['document-fragment']
52+
expected = self.test['document']
53+
expectedErrors = self.test['errors'].split("\n") if self.test['errors'] else []
54+
55+
with warnings.catch_warnings():
56+
warnings.simplefilter("error")
57+
try:
58+
if fragmentContainer:
59+
document = p.parseFragment(input, fragmentContainer)
60+
else:
61+
document = p.parse(input)
62+
except constants.DataLossWarning:
63+
pytest.skip("data loss warning")
64+
65+
output = convertTreeDump(p.tree.testSerializer(document))
66+
67+
expected = convertExpected(expected)
68+
if self.namespaceHTMLElements:
69+
expected = namespaceExpected(r"\1<html \2>", expected)
70+
71+
errorMsg = "\n".join(["\n\nInput:", input, "\nExpected:", expected,
72+
"\nReceived:", output])
73+
assert expected == output, errorMsg
74+
75+
errStr = []
76+
for (line, col), errorcode, datavars in p.errors:
77+
assert isinstance(datavars, dict), "%s, %s" % (errorcode, repr(datavars))
78+
errStr.append("Line: %i Col: %i %s" % (line, col,
79+
constants.E[errorcode] % datavars))
80+
81+
errorMsg2 = "\n".join(["\n\nInput:", input,
82+
"\nExpected errors (" + str(len(expectedErrors)) + "):\n" + "\n".join(expectedErrors),
83+
"\nActual errors (" + str(len(p.errors)) + "):\n" + "\n".join(errStr)])
84+
if False: # we're currently not testing parse errors
85+
assert len(p.errors) == len(expectedErrors), errorMsg2
86+
87+
def repr_failure(self, excinfo):
88+
traceback = excinfo.traceback
89+
ntraceback = traceback.cut(path=__file__)
90+
excinfo.traceback = ntraceback.filter()
91+
92+
return excinfo.getrepr(funcargs=True,
93+
showlocals=False,
94+
style="short", tbfilter=False)

Diff for: pytest.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
[pytest]
2-
addopts = -rXw -p no:doctest
2+
addopts = -rXw -p no:doctest

0 commit comments

Comments
 (0)