summaryrefslogtreecommitdiff
path: root/simple_unit_tests.py
diff options
context:
space:
mode:
authorptmcg <ptmcg@austin.rr.com>2018-09-19 19:55:51 -0500
committerptmcg <ptmcg@austin.rr.com>2018-09-19 19:55:51 -0500
commit4dce0936aec1494076b8bb7f87f894e52bffe04d (patch)
tree5ac7fc235a537d071b612f1a84b6d91a3ada5586 /simple_unit_tests.py
parent952eea0d744b79550579dc4c435d462ac4519835 (diff)
downloadpyparsing-git-4dce0936aec1494076b8bb7f87f894e52bffe04d.tar.gz
fix import of pyparsing from simple_unit_tests.py
Diffstat (limited to 'simple_unit_tests.py')
-rw-r--r--simple_unit_tests.py160
1 files changed, 160 insertions, 0 deletions
diff --git a/simple_unit_tests.py b/simple_unit_tests.py
new file mode 100644
index 0000000..d2795b5
--- /dev/null
+++ b/simple_unit_tests.py
@@ -0,0 +1,160 @@
+#
+# simple_unit_tests.py
+#
+# While these unit tests *do* perform low-level unit testing of the classes in pyparsing,
+# this testing module should also serve an instructional purpose, to clearly show simple passing
+# and failing parse cases of some basic pyparsing expressions.
+#
+# Copyright (c) 2018 Paul T. McGuire
+#
+
+import unittest
+import pyparsing as pp
+from collections import namedtuple
+
+# Test spec data class for specifying simple pyparsing test cases
+PpTestSpec = namedtuple("PpTestSpec", "desc expr text expected_list expected_dict expected_fail_locn")
+PpTestSpec.__new__.__defaults__ = ('', pp.Empty(), '', None, None, None)
+
+
+class PyparsingExpressionTestCase(unittest.TestCase):
+ """
+ Base pyparsing testing class to parse various pyparsing expressions against
+ given text strings. Subclasses must define a class attribute 'tests' which
+ is a list of PpTestSpec instances.
+ """
+ def test_match(self):
+ if self.__class__ is PyparsingExpressionTestCase:
+ return
+
+ for test_spec in self.tests:
+ # for each spec in the class's tests list, create a subtest
+ # that will either:
+ # - parse the string with expected success, display the
+ # results, and validate the returned ParseResults
+ # - or parse the string with expected failure, display the
+ # error message and mark the error location, and validate
+ # the location against an expected value
+ with self.subTest(test_spec=test_spec):
+ test_spec.expr.streamline()
+ print("\n{} - {}({})".format(test_spec.desc,
+ type(test_spec.expr).__name__,
+ test_spec.expr))
+
+ if test_spec.expected_fail_locn is None:
+ # expect success
+ result = test_spec.expr.parseString(test_spec.text)
+ print(result.dump())
+ # compare results against given list and/or dict
+ if test_spec.expected_list is not None:
+ self.assertEqual(result.asList(), test_spec.expected_list)
+ if test_spec.expected_dict is not None:
+ self.assertEqual(result.asDict(), test_spec.expected_dict)
+
+ else:
+ # expect fail
+ with self.assertRaises(pp.ParseException) as ar:
+ test_spec.expr.parseString(test_spec.text)
+ print(' ', test_spec.text or "''")
+ print(' ', ' '*ar.exception.loc+'^')
+ print(' ', ar.exception.msg)
+ self.assertEqual(ar.exception.loc, test_spec.expected_fail_locn)
+
+
+
+class TestLiteral(PyparsingExpressionTestCase):
+ tests = [
+ PpTestSpec(
+ desc = "Simple match",
+ expr = pp.Literal("xyz"),
+ text = "xyz",
+ expected_list = ["xyz"],
+ ),
+ PpTestSpec(
+ desc = "Simple match after skipping whitespace",
+ expr = pp.Literal("xyz"),
+ text = " xyz",
+ expected_list = ["xyz"],
+ ),
+ PpTestSpec(
+ desc = "Simple fail - parse an empty string",
+ expr = pp.Literal("xyz"),
+ text = "",
+ expected_fail_locn = 0,
+ ),
+ PpTestSpec(
+ desc = "Simple fail - parse a mismatching string",
+ expr = pp.Literal("xyz"),
+ text = "xyu",
+ expected_fail_locn = 0,
+ ),
+ PpTestSpec(
+ desc = "Simple fail - parse a partially matching string",
+ expr = pp.Literal("xyz"),
+ text = "xy",
+ expected_fail_locn = 0,
+ ),
+ PpTestSpec(
+ desc = "Fail - parse a partially matching string by matching individual letters",
+ expr = pp.Literal("x") + pp.Literal("y") + pp.Literal("z"),
+ text = "xy",
+ expected_fail_locn = 2,
+ ),
+ ]
+
+
+class TestWord(PyparsingExpressionTestCase):
+ tests = [
+ PpTestSpec(
+ desc = "Simple Word match",
+ expr = pp.Word("xy"),
+ text = "xxyxxyy",
+ expected_list = ["xxyxxyy"],
+ ),
+ PpTestSpec(
+ desc = "Simple Word match of two separate Words",
+ expr = pp.Word("x") + pp.Word("y"),
+ text = "xxxxxyy",
+ expected_list = ["xxxxx", "yy"],
+ ),
+ PpTestSpec(
+ desc = "Simple Word match of two separate Words - implicitly skips whitespace",
+ expr = pp.Word("x") + pp.Word("y"),
+ text = "xxxxx yy",
+ expected_list = ["xxxxx", "yy"],
+ ),
+ ]
+
+
+class TestResultsName(PyparsingExpressionTestCase):
+ tests = [
+ PpTestSpec(
+ desc = "Match with results name",
+ expr = pp.Literal("xyz").setResultsName("value"),
+ text = "xyz",
+ expected_dict = {'value': 'xyz'},
+ expected_list = ['xyz'],
+ ),
+ PpTestSpec(
+ desc = "Match with results name - using naming short-cut",
+ expr = pp.Literal("xyz")("value"),
+ text = "xyz",
+ expected_dict = {'value': 'xyz'},
+ expected_list = ['xyz'],
+ ),
+ ]
+
+
+class TestParseAction(PyparsingExpressionTestCase):
+ tests = [
+ PpTestSpec(
+ desc = "Match with numeric string converted to int",
+ expr = pp.Word("0123456789").addParseAction(lambda t: int(t[0])),
+ text = "12345",
+ expected_list = [12345], # note - result is type int, not str
+ ),
+ ]
+
+
+if __name__ == '__main__':
+ unittest.main() \ No newline at end of file