Skip to content

Commit

Permalink
Merge pull request #18 from AnjoMan/readible-test-expectations
Browse files Browse the repository at this point in the history
Refactor tests for readible output
  • Loading branch information
tomchristie committed Mar 3, 2020
2 parents 01713b0 + 1ae0daf commit 7807afb
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 25 deletions.
Empty file added tests/__init__.py
Empty file.
71 changes: 71 additions & 0 deletions tests/assertions.py
@@ -0,0 +1,71 @@
from xml import etree
from xml.dom import minidom
import textwrap


def assert_xml_equal(xml_string, expected_xml_string):
"""
Assert equality of two xml strings, particularly that the contents of
each string have the same elements, with the same attributes (e.g. class,
text) and the same non-xml string contents
"""
# this prints a human-formatted string of what the test passed in -- useful
# if you need to modify test expectations after you've modified
# a rendering and tested it visually
print(to_readable_error_output(xml_string))

assert_elements_equal(
etree.ElementTree.fromstring(tostring(xml_string)),
etree.ElementTree.fromstring(tostring(expected_xml_string)),
)


def assert_elements_equal(element, reference_element):
"""
Assert, recursively, the equality of two etree objects.
"""
assert (
element.text == reference_element.text
), f"Text doesn't match: {element.text} =/= {reference_element.text}."
assert (
element.attrib == reference_element.attrib
), f"Attrib doesn't match: {element.attrib} =/= {reference_element.attrib}"
assert len(element) == len(
reference_element
), f"Expected {len(reference_element)} children but got {len(element)}"
for sub_element, reference_sub_element in zip(element, reference_element):
assert_elements_equal(sub_element, reference_sub_element)


def tostring(xml_string):
"""
Wraps `xml_string` in a div so it can be rendered, even if it has multiple roots.
"""
return remove_indents(f"<div>{remove_indents(xml_string)}</div>").encode("utf-8")


def to_readable_error_output(xml_string):
return textwrap.dedent(
"\n".join(
minidom.parseString(tostring(xml_string))
.toprettyxml(indent=" ")
.split("\n")[2:-2] # remove xml declaration and div added by `tostring`
)
) # dent by " "


def remove_indents(html):
"""
Remove leading whitespace from a string
e.g.
input: output:
. <div> . <div>
. <p>Some Text</p> . <p>Some Text</p>
. <div> . <div>
. Some more text . Some more text
. </div> . </div>
. </div> . </div>
"""
lines = [el.lstrip() for el in html.split("\n")]
return "".join([el for el in lines if el or el != "\n"])
118 changes: 93 additions & 25 deletions tests/test_extension.py
@@ -1,4 +1,5 @@
import markdown
from .assertions import assert_xml_equal


def test_docstring():
Expand All @@ -9,25 +10,55 @@ def test_docstring():
:docstring:
"""
output = markdown.markdown(content, extensions=["mkautodoc"])
assert output.splitlines() == [
"<h1>Example</h1>",
'<div class="autodoc">',
'<div class="autodoc-signature"><code>mocklib.<strong>example_function</strong></code><span class="autodoc-punctuation">(</span><em class="autodoc-param">a</em><span class="autodoc-punctuation">, </span><em class="autodoc-param">b=None</em><span class="autodoc-punctuation">, </span><em class="autodoc-param">*args</em><span class="autodoc-punctuation">, </span><em class="autodoc-param">**kwargs</em><span class="autodoc-punctuation">)</span></div>',
'<div class="autodoc-docstring"><p>This is a function with a <em>docstring</em>.</p></div>',
"</div>",
]
assert_xml_equal(
output,
"""
<h1>Example</h1>
<div class="autodoc">
<div class="autodoc-signature">
<code>
mocklib.
<strong>example_function</strong>
</code>
<span class="autodoc-punctuation">(</span>
<em class="autodoc-param">a</em>
<span class="autodoc-punctuation">, </span>
<em class="autodoc-param">b=None</em>
<span class="autodoc-punctuation">, </span>
<em class="autodoc-param">*args</em>
<span class="autodoc-punctuation">, </span>
<em class="autodoc-param">**kwargs</em>
<span class="autodoc-punctuation">)</span>
</div>
<div class="autodoc-docstring">
<p>
This is a function with a <em>docstring</em>.
</p>
</div>
</div>""",
)


def test_async_function():
content = """
::: mocklib.example_async_function
"""
output = markdown.markdown(content, extensions=["mkautodoc"])
assert output.splitlines() == [
'<div class="autodoc">',
'<div class="autodoc-signature"><em>async </em><code>mocklib.<strong>example_async_function</strong></code><span class="autodoc-punctuation">(</span><span class="autodoc-punctuation">)</span></div>',
"</div>",
]
assert_xml_equal(
output,
"""
<div class="autodoc">
<div class="autodoc-signature">
<em>async </em>
<code>
mocklib.
<strong>example_async_function</strong>
</code>
<span class="autodoc-punctuation">(</span>
<span class="autodoc-punctuation">)</span>
</div>
</div>""",
)


def test_members():
Expand All @@ -39,16 +70,53 @@ def test_members():
:members:
"""
output = markdown.markdown(content, extensions=["mkautodoc"])
assert output.splitlines() == [
"<h1>Example</h1>",
'<div class="autodoc">',
'<div class="autodoc-signature"><em>class </em><code>mocklib.<strong>ExampleClass</strong></code><span class="autodoc-punctuation">(</span><span class="autodoc-punctuation">)</span></div>',
'<div class="autodoc-docstring"><p>This is a class with a <em>docstring</em>.</p></div>',
'<div class="autodoc-members">',
'<div class="autodoc-signature"><code><strong>example_method</strong></code><span class="autodoc-punctuation">(</span><em class="autodoc-param">self</em><span class="autodoc-punctuation">, </span><em class="autodoc-param">a</em><span class="autodoc-punctuation">, </span><em class="autodoc-param">b=None</em><span class="autodoc-punctuation">)</span></div>',
'<div class="autodoc-docstring"><p>This is a method with a <em>docstring</em>.</p></div>',
'<div class="autodoc-signature"><code><strong>example_property</strong></code></div>',
'<div class="autodoc-docstring"><p>This is a property with a <em>docstring</em>.</p></div>',
"</div>",
"</div>",
]
assert_xml_equal(
output,
"""
<h1>Example</h1>
<div class="autodoc">
<div class="autodoc-signature">
<em>class </em>
<code>
mocklib.
<strong>ExampleClass</strong>
</code>
<span class="autodoc-punctuation">(</span>
<span class="autodoc-punctuation">)</span>
</div>
<div class="autodoc-docstring">
<p>
This is a class with a <em>docstring</em>.
</p>
</div>
<div class="autodoc-members">
<div class="autodoc-signature">
<code>
<strong>example_method</strong>
</code>
<span class="autodoc-punctuation">(</span>
<em class="autodoc-param">self</em>
<span class="autodoc-punctuation">, </span>
<em class="autodoc-param">a</em>
<span class="autodoc-punctuation">, </span>
<em class="autodoc-param">b=None</em>
<span class="autodoc-punctuation">)</span>
</div>
<div class="autodoc-docstring">
<p>
This is a method with a <em>docstring</em>.
</p>
</div>
<div class="autodoc-signature">
<code>
<strong>example_property</strong>
</code>
</div>
<div class="autodoc-docstring">
<p>
This is a property with a <em>docstring</em>.
</p>
</div>
</div>
</div>""",
)

0 comments on commit 7807afb

Please sign in to comment.