{ "info": { "author": "Jim Fulton", "author_email": "jim@zope.com", "bugtrack_url": null, "classifiers": [], "description": "HTML/DOM Checker\n================\n\nWhen testing code (like widgets) that generates DOM nodes, we want to\nbe able to make assertions about what matters. Examples of things we'd\nlike to ignore:\n\n- attribute order\n- extra attributes\n- attribute order\n- extra classes\n- extra nodes\n\nzc.htmlchecker provides a checker object that can be used by itself,\nor as a doctest output checker.\n\n.. contents::\n\nGetting started\n---------------\n\nLet's look at some examples.\n\nHere's a sample expected string::\n\n \n \n \n\n.. -> expected\n\nLet's create a checker:\n\n >>> import zc.htmlchecker\n >>> checker = zc.htmlchecker.HTMLChecker()\n\nYou can call its check method with expected and observed HTML:\n\n >>> checker.check(\n ... expected,\n ... \"\"\"\n ... \"\"\")\n\nIf there's a match, then nothing is returned. For there to be a\nmatch, the expected output merely has to be unambiguously found in the\nobserved output. In the above example, there was a single body tag,\nso it knew how to do the match. Note that whitespace differences were\nignored, as were extra observed attributes and an extra class.\n\ndoctest Checker\n---------------\n\nTo use ``zc.htmlchecker`` as a doctest checker, pass an instance of\n``HTMLChecker`` as an output checker when setting up your doctests.\n\n.. low-level doctest checker tests\n\n When used as a doctest output checker, its ``check_output`` method\n returns a boolean indicating whether there was a match:\n\n >>> checker.check_output(\n ... expected,\n ... \"\"\"\n ... \"\"\", 0)\n True\n\n And the ``output_difference`` shows differences. It's a little weird\n (not our fault) in that it takes an example, rather than a wanted\n text:\n\n >>> class Example:\n ... def __init__(self, want): self.want = want\n >>> checker.output_difference(\n ... Example(expected),\n ... \"\"\"\n ... \"\"\", 0)\n ''\n\n Now let's make it fail:\n\n >>> checker.check(\n ... expected,\n ... \"\"\"\n ... \"\"\")\n Traceback (most recent call last):\n ...\n MatchError: missing class: mybutton\n Expected:\n \n \n Observed:\n \n \n\n >>> checker.check_output(\n ... expected,\n ... \"\"\"\n ... \"\"\", 0)\n False\n\n >>> print checker.output_difference(\n ... Example(expected),\n ... \"\"\"\n ... \"\"\", 0),\n missing class: mybutton\n Expected:\n \n \n Observed:\n \n\nWhen used as a doctest checker, expected text that doesn't start with\n``<`` is checked with the default checker, or a checker you pass in as\nbase.\n\n.. test above\n\n >>> checker.check_output('1', '2', 0)\n False\n\n >>> import doctest\n >>> checker.check_output('1...3', '123', doctest.ELLIPSIS)\n True\n\n >>> class FooChecker:\n ... def check_output(self, want, got, flags):\n ... return 'foo' in got.lower()\n\n >>> checker2 = zc.htmlchecker.HTMLChecker(FooChecker())\n >>> checker2.check_output('1', '2 foo', 0)\n True\n >>> checker2.check_output('', '2 foo', 0)\n False\n\nYou may want to have some html examples checked with another\nchecker. In that case, you can specify a prefix. Only examples that\nbegin with the prefix will be checked with the HTML checker, and the\nprefix will be removed.\n\n.. test above\n\n >>> checker2 = zc.htmlchecker.HTMLChecker(FooChecker(), prefix=\"<>\")\n >>> checker2.check_output('', '2 foo', 0)\n True\n >>> checker2.check_output('<>', '2 foo', 0)\n False\n >>> checker2.check_output('<>', '', 0)\n True\n\n >>> checker3 = zc.htmlchecker.HTMLChecker(prefix=\"<>\")\n >>> checker3.check_output('<>', '', 0)\n True\n >>> checker3.check_output('', '', 0)\n False\n\n >>> print checker3.output_difference(Example(''), '', 0)\n Expected:\n Got:\n \n\n >>> print checker3.output_difference(Example('<>'), '', 0)\n Couldn't find wildcard match\n Expected:\n \n \n Observed:\n \n \n\nExpecting multiple nodes\n------------------------\n\nWe can expect more than a single node::\n\n \n \n\n.. -> expected\n\nThis example expects 2 button nodes somewhere in the output.\n\n >>> checker.check(expected,\n ... \"\"\"\n ... \n ... \n ... \"\"\")\n\nBut if there isn't a match, it can be harder to figure out what's\nwrong:\n\n >>> checker.check(expected,\n ... \"\"\"\n ... \n ... \n ... \"\"\")\n Traceback (most recent call last):\n ...\n MatchError: Couldn't find wildcard match\n Expected:\n \n \n Observed:\n \n \n \n \n \n \n\nWe'll come back to wild card matches in a bit. Here, the matcher\ndetected that it didn't match a button, but couldn't be specific about\nwhich button was the problem. We can make its job easier using ids::\n\n \n \n\n.. -> expected\n\nNow we're looking for button nodes with specific ids.\n\n >>> checker.check(expected,\n ... \"\"\"\n ... \n ... \n ... \"\"\")\n Traceback (most recent call last):\n ...\n MatchError: text nodes differ u'Save' != u'OK'\n Expected:\n \n \n Observed:\n \n \n\nThat's a lot more helpful.\n\nWildcards\n---------\n\nSpeaking of wild card matches, sometimes you want to ignore\nintermediate nodes. You can do this by using an ellipsis at the top of\na node that has intermediate nodes you want to ignore::\n\n
\n ...\n \n \n
\n\n.. -> expected\n\nIn this case, we want to find button nodes inside a form node. We\ndon't care if there are intermediate nodes.\n\n >>> checker.check(expected,\n ... \"\"\"\n ...
\n ...
\n ... \n ... \n ...
\n ...
\n ... \"\"\")\n\nWhen looking for expected text, we basically do a wild-card match on\nthe observed text.\n\nSometimes, we want to check for text nodes that may be embedded in\nsome generated construct that we can't control (like a grid produced\nby a library). To do that, include a text node that starts with a\nline containing an ellipsis. For example, we may expect a grid/table\nwith some data::\n\n
\n ...\n Name Favorite Color\n Sally Red\n Bill Blue\n
\n\n.. -> expected\n\nWe don't know exactly how our library is going to wrap the data, so we\njust test for the presense of the data.\n\n >>> import sys\n >>> try: checker.check(expected,\n ... \"\"\"\n ...
\n ... \n ... \n ... \n ... \n ...
NameFavorite Color
SallyRed
Bill Green
\n ...
\n ... \"\"\")\n ... except zc.htmlchecker.MatchError:\n ... error = sys.exc_info()[1]\n ... else: print 'oops'\n >>> print error # doctest: +ELLIPSIS\n Blue not found in text content.\n ...\n\n >>> checker.check(expected,\n ... \"\"\"\n ...
\n ... \n ... \n ... \n ... \n ...
NameFavorite Color
SallyRed
Bill Blue
\n ...
\n ... \"\"\")\n\n\n\n\n\nYou can use other BeautifulSoup parsers\n---------------------------------------\n\nHTMLChecker uses BeautifulSoup. It uses the ``'html5lib'`` parser by\ndefault, but you can pass a different parser name. You probably want\nto stere clear of the ``'html.parser'`` parser, as it's buggy:\n\n >>> checker = zc.htmlchecker.HTMLChecker(parser='html.parser')\n >>> checker.check('', '')\n Traceback (most recent call last):\n ...\n MatchError: Wrong number of children 1!=0\n Expected:\n \n \n Observed:\n \n \n \n\nHere, ``'html.parser'`` decided that the input tags needed closing\ntags, even though the HTML input tag is empty. This is likely in part\nbecause the underlying parser is an XHTML parser.\n\nChanges\n=======\n\n0.1.0 2013-08-31\n----------------\n\nInitial release.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "UNKNOWN", "keywords": null, "license": "ZPL 2.1", "maintainer": null, "maintainer_email": null, "name": "zc.htmlchecker", "package_url": "https://pypi.org/project/zc.htmlchecker/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/zc.htmlchecker/", "project_urls": { "Download": "UNKNOWN", "Homepage": "UNKNOWN" }, "release_url": "https://pypi.org/project/zc.htmlchecker/0.1.0/", "requires_dist": null, "requires_python": null, "summary": "HTML/DOM Checker", "version": "0.1.0" }, "last_serial": 853806, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "ec11f45b23a9fbd24662902fa35fd975", "sha256": "2948437f2490f9674d33c785eeaa7fc75ebf1c93c81495f8a741146288e58635" }, "downloads": -1, "filename": "zc.htmlchecker-0.1.0.tar.gz", "has_sig": false, "md5_digest": "ec11f45b23a9fbd24662902fa35fd975", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9321, "upload_time": "2013-08-31T16:33:11", "url": "https://files.pythonhosted.org/packages/ef/da/b2b39c7b21b7e48a95a66de4b10e90f8f5c0cd3a481c860d66836ad613e3/zc.htmlchecker-0.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "ec11f45b23a9fbd24662902fa35fd975", "sha256": "2948437f2490f9674d33c785eeaa7fc75ebf1c93c81495f8a741146288e58635" }, "downloads": -1, "filename": "zc.htmlchecker-0.1.0.tar.gz", "has_sig": false, "md5_digest": "ec11f45b23a9fbd24662902fa35fd975", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9321, "upload_time": "2013-08-31T16:33:11", "url": "https://files.pythonhosted.org/packages/ef/da/b2b39c7b21b7e48a95a66de4b10e90f8f5c0cd3a481c860d66836ad613e3/zc.htmlchecker-0.1.0.tar.gz" } ] }