onadata.libs.test_utils package

Submodules

onadata.libs.test_utils.md_table module

Markdown table utility functions.

onadata.libs.test_utils.md_table.md_table_to_ss_structure(mdstr: str) List[Tuple[str, List[List[str]]]]

Transform markdown to an ss structure

onadata.libs.test_utils.md_table.md_table_to_workbook(mdstr: str) Workbook

Convert Markdown table string to an openpyxl.Workbook. Call workbook.save() to persist.

onadata.libs.test_utils.pyxform_test_case module

PyxformTestCase base class using markdown to define the XLSForm.

class onadata.libs.test_utils.pyxform_test_case.MatcherContext(debug: bool, nsmap_xpath: Dict[str, str], nsmap_subs: NSMAPSubs, content_str: str)

Bases: object

Data class to store assertion context information.

content_str: str
debug: bool
nsmap_subs: NSMAPSubs
nsmap_xpath: Dict[str, str]
class onadata.libs.test_utils.pyxform_test_case.PyxformMarkdown

Bases: object

Transform markdown formatted XLSForm to a pyxform survey object

md_to_pyxform_survey(md_raw, kwargs=None, autoname=True, warnings=None)

Transform markdown formatted XLSForm to pyxform survey object.

class onadata.libs.test_utils.pyxform_test_case.PyxformTestCase(methodName='runTest')

Bases: PyxformMarkdown, TestCase

The pyxform markdown TestCase class

assertContains(content, text, count=None, msg_prefix='')

FROM: django source- testcases.py

Asserts that text occurs count times in the content string. If count is None, the count doesn’t matter - the assertion is true if the text occurs at least once in the content.

assertNotContains(content, text, msg_prefix='')

Asserts that a content indicates that some content was retrieved successfully, (i.e., the HTTP status code was as expected), and that text doesn’t occurs in the content of the content.

assertPyxformXform(**kwargs)

PyxformTestCase.assertPyxformXform() named arguments:

one of these possible survey input types
  • md: (str) a markdown formatted xlsform (easy to read in code)
    [consider a plugin to help with formatting md tables,

    e.g. https://github.com/vkocubinsky/SublimeTableEditor]

  • ss_structure: (dict) a python dictionary with sheets and their

    contents. best used in cases where testing whitespace and cells’ type is important

  • survey: (pyxform.survey.Survey) easy for reuse within a test

# Note: XLS is not implemented at this time. You can use builder to create a pyxform Survey object

one or many of these string “matchers”:
  • xml__contains: an array of strings which exist in the

    resulting xml. [xml|model|instance|itext]_excludes are also supported.

  • error__contains: a list of strings which should exist in the error

  • error__not_contains: a list of strings which should not exist in

    the error

  • odk_validate_error__contains: list of strings; run_odk_validate

    must be set

  • warnings__contains: a list of strings which should exist in the

    warnings

  • warnings__not_contains: a list of strings which should not

    exist in the warnings

  • warnings_count: the number of expected warning messages

  • xml__excludes: an array of strings which should not exist in the

    resulting xml. [xml|model|instance|itext]_excludes are also supported.

  • xml__xpath_exact: A list of tuples where the first tuple element

    is an XPath expression and the second tuple element is a set of exact string match results that are expected.

  • xml__xpath_count: A list of tuples where the first tuple element

    is_an XPath expression and the second tuple element is the integer number of match results that are expected.

  • xml__xpath_match: A list of XPath expression strings for which

    exactly one match result each is expected. Effectively a shortcut for xml__xpath_count with a count of 1.

For each of the xpath_* matchers above, if the XPath expression is looking for an element in the ‘default’ namespace (xforms) then use an ‘x’ namespace prefix for the element. For example to find input nodes in the body: “.//h:body/x:input”. This ‘x’ prefix is not required for attributes. When writing a xpath_* test, use debug=True to show the XPath match results.

optional other parameters passed to pyxform:
  • errored: (bool) if the xlsform is not supposed to compile,

    this must be True

  • name: (str) a valid xml tag to be used as the form name

  • id_string: (str)

  • title: (str)

  • run_odk_validate: (bool) when True, runs ODK Validate process

    Default value = False because it slows down tests

  • warnings: (list) a list to use for storing warnings for inspection.

  • debug: (bool) when True, log details of the test to stdout.

    Details include the input survey markdown, the XML document, XPath match strings.

assert_xpath_count(matcher_context: MatcherContext, content: _Element, xpath: str, expected: int)

Process an assertion for xml__xpath_count.

Parameters:
  • matcher_context – A MatcherContext dataclass.

  • content – XML to be examined.

  • xpath – XPath to execute.

  • expected – Expected count of XPath matches.

assert_xpath_exact(matcher_context: MatcherContext, content: _Element, xpath: str, expected: Set[str]) None

Process an assertion for xml__xpath_exact.

Compares result strings since expected strings may contain xml namespace prefixes. To allow parsing required to compare as ETrees would require injecting namespace declarations into the expected match strings.

Parameters:
  • matcher_context – A MatcherContext dataclass.

  • content – XML to be examined.

  • xpath – XPath to execute.

  • expected – Expected XPath matches, as XML fragments.

maxDiff = None
exception onadata.libs.test_utils.pyxform_test_case.PyxformTestError

Bases: Exception

Pyxform test errors exception class.

onadata.libs.test_utils.pyxform_test_case.reorder_attributes(root)

Forces alphabetical ordering of all XML attributes to match pre Python 3.8 behaviour. In general, we should not rely on ordering, but changing all the tests is not realistic at this moment.

See bottom of https://bit.ly/38docMg and https://bit.ly/3ODx9iG for more information.

NOTE: there’s a similar ordering change made in utils.node. This one is also needed because in assertPyxformXform, the survey is converted to XML and then read back in using ETree.fromstring. This means that attribute ordering here is based on the attribute representation of xml.etree.ElementTree objects. In utils.node, it is based on xml.dom.minidom.Element objects. See https://github.com/XLSForm/pyxform/issues/414.

onadata.libs.test_utils.pyxform_test_case.xpath_clean_result_strings(nsmap_subs: NSMAPSubs, results: Set[_Element]) Set[str]

Clean XPath results: stringify, remove namespace declarations, clean up whitespace.

Parameters:
onadata.libs.test_utils.pyxform_test_case.xpath_evaluate(matcher_context: MatcherContext, content: _Element, xpath: str, for_exact=False) Set[_Element] | Set[str]

Evaluate an XPath and return the results.

Parameters:
  • matcher_context – A MatcherContext dataclass.

  • content – XML to be examined.

  • xpath – XPath to execute.

  • for_exact – If True, convert the results to strings and perform clean-up. If False, return the set of Element (or attribute string) matches as-is.

Returns:

Module contents