From 1ae0daf7a35bc026c02a5db3d33815775e076836 Mon Sep 17 00:00:00 2001 From: Anton Lodder Date: Fri, 7 Feb 2020 09:34:41 -0500 Subject: [PATCH] Refactor tests for readible output --- tests/__init__.py | 0 tests/assertions.py | 71 ++++++++++++++++++++++++ tests/test_extension.py | 118 +++++++++++++++++++++++++++++++--------- 3 files changed, 164 insertions(+), 25 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/assertions.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/assertions.py b/tests/assertions.py new file mode 100644 index 0000000..14d21f6 --- /dev/null +++ b/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"
{remove_indents(xml_string)}
").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: + .
.
+ .

Some Text

.

Some Text

+ .
.
+ . Some more text . Some more text + .
.
+ .
.
+ """ + lines = [el.lstrip() for el in html.split("\n")] + return "".join([el for el in lines if el or el != "\n"]) diff --git a/tests/test_extension.py b/tests/test_extension.py index 854d3ee..4600361 100644 --- a/tests/test_extension.py +++ b/tests/test_extension.py @@ -1,4 +1,5 @@ import markdown +from .assertions import assert_xml_equal def test_docstring(): @@ -9,13 +10,33 @@ def test_docstring(): :docstring: """ output = markdown.markdown(content, extensions=["mkautodoc"]) - assert output.splitlines() == [ - "

Example

", - '
', - '
mocklib.example_function(a, b=None, *args, **kwargs)
', - '

This is a function with a docstring.

', - "
", - ] + assert_xml_equal( + output, + """ +

Example

+
+
+ + mocklib. + example_function + + ( + a + , + b=None + , + *args + , + **kwargs + ) +
+
+

+ This is a function with a docstring. +

+
+
""", + ) def test_async_function(): @@ -23,11 +44,21 @@ def test_async_function(): ::: mocklib.example_async_function """ output = markdown.markdown(content, extensions=["mkautodoc"]) - assert output.splitlines() == [ - '
', - '
async mocklib.example_async_function()
', - "
", - ] + assert_xml_equal( + output, + """ +
+
+ async + + mocklib. + example_async_function + + ( + ) +
+
""", + ) def test_members(): @@ -39,16 +70,53 @@ def test_members(): :members: """ output = markdown.markdown(content, extensions=["mkautodoc"]) - assert output.splitlines() == [ - "

Example

", - '
', - '
class mocklib.ExampleClass()
', - '

This is a class with a docstring.

', - '
', - '
example_method(self, a, b=None)
', - '

This is a method with a docstring.

', - '
example_property
', - '

This is a property with a docstring.

', - "
", - "
", - ] + assert_xml_equal( + output, + """ +

Example

+
+
+ class + + mocklib. + ExampleClass + + ( + ) +
+
+

+ This is a class with a docstring. +

+
+
+
+ + example_method + + ( + self + , + a + , + b=None + ) +
+
+

+ This is a method with a docstring. +

+
+
+ + example_property + +
+
+

+ This is a property with a docstring. +

+
+
+
""", + )