<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Thanks for the help! I’ve just released the plugin on PyPI:<div class=""><a href="https://pypi.python.org/pypi/pytest-html" class="">https://pypi.python.org/pypi/pytest-html</a><div class=""><div class=""><br class=""></div><div apple-content-edited="true" class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">--</div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><strong class="">Dave Hunt</strong></div><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="moz-signature">Firefox OS Automation Engineer<br class="">Mozilla Corporation<br class="">dhunt@mozilla.com</div></div>
</div>
<br class=""><div><blockquote type="cite" class=""><div class="">On 19 Apr 2015, at 09:16, holger krekel <holger@merlinux.eu> wrote:</div><br class="Apple-interchange-newline"><div class="">On Thu, Apr 16, 2015 at 17:46 +0100, Dave Hunt wrote:<br class=""><blockquote type="cite" class="">Thanks Bruno, the custom hook works well. Here’s the change: https://github.com/davehunt/pytest-html/commit/2a405a3cdc638c1896ab3d1074296496bb1fa3a8 <https://github.com/davehunt/pytest-html/commit/2a405a3cdc638c1896ab3d1074296496bb1fa3a8><br class=""><br class="">Now I need to work out why I get issues when I use this with pytest-xdist. It looks like it’s complaining about the extra report details not being serializable?! See traceback below:<br class=""></blockquote><br class="">Yes, you need to make sure that anything extra you put on the report is marshallable.<br class="">In the case of your url you may just send a string and parse as url on<br class="">the logreport/master side.<br class=""><br class="">holger<br class=""><br class=""><br class=""><blockquote type="cite" class="">test_login.py::TestLogin::test_invalid_username INTERNALERROR> Traceback (most recent call last):<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/main.py", line 84, in wrap_session<br class="">INTERNALERROR>     doit(config, session)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/main.py", line 122, in _main<br class="">INTERNALERROR>     config.hook.pytest_runtestloop(session=session)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 521, in __call__<br class="">INTERNALERROR>     return self._docall(self.methods, kwargs)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 528, in _docall<br class="">INTERNALERROR>     firstresult=self.firstresult).execute()<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 394, in execute<br class="">INTERNALERROR>     res = method(*args)<br class="">INTERNALERROR>   File "<remote exec>", line 56, in pytest_runtestloop<br class="">INTERNALERROR>   File "<remote exec>", line 72, in run_tests<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 521, in __call__<br class="">INTERNALERROR>     return self._docall(self.methods, kwargs)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 528, in _docall<br class="">INTERNALERROR>     firstresult=self.firstresult).execute()<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 393, in execute<br class="">INTERNALERROR>     return wrapped_call(method(*args), self.execute)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 113, in wrapped_call<br class="">INTERNALERROR>     return call_outcome.get_result()<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 138, in get_result<br class="">INTERNALERROR>     py.builtin._reraise(*ex)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 123, in __init__<br class="">INTERNALERROR>     self.result = func()<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 394, in execute<br class="">INTERNALERROR>     res = method(*args)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/runner.py", line 65, in pytest_runtest_protocol<br class="">INTERNALERROR>     runtestprotocol(item, nextitem=nextitem)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/runner.py", line 75, in runtestprotocol<br class="">INTERNALERROR>     reports.append(call_and_report(item, "call", log))<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/runner.py", line 123, in call_and_report<br class="">INTERNALERROR>     hook.pytest_runtest_logreport(report=report)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 521, in __call__<br class="">INTERNALERROR>     return self._docall(self.methods, kwargs)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 528, in _docall<br class="">INTERNALERROR>     firstresult=self.firstresult).execute()<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 394, in execute<br class="">INTERNALERROR>     res = method(*args)<br class="">INTERNALERROR>   File "<remote exec>", line 86, in pytest_runtest_logreport<br class="">INTERNALERROR>   File "<remote exec>", line 23, in sendevent<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 691, in send<br class="">INTERNALERROR>     self.gateway._send(Message.CHANNEL_DATA, self.id, dumps_internal(item))<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1295, in dumps_internal<br class="">INTERNALERROR>     return _Serializer().save(obj)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1313, in save<br class="">INTERNALERROR>     self._save(obj)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1331, in _save<br class="">INTERNALERROR>     dispatch(self, obj)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1412, in save_tuple<br class="">INTERNALERROR>     self._save(item)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1331, in _save<br class="">INTERNALERROR>     dispatch(self, obj)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1408, in save_dict<br class="">INTERNALERROR>     self._write_setitem(key, value)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1402, in _write_setitem<br class="">INTERNALERROR>     self._save(value)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1331, in _save<br class="">INTERNALERROR>     dispatch(self, obj)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1408, in save_dict<br class="">INTERNALERROR>     self._write_setitem(key, value)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1402, in _write_setitem<br class="">INTERNALERROR>     self._save(value)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1331, in _save<br class="">INTERNALERROR>     dispatch(self, obj)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1398, in save_list<br class="">INTERNALERROR>     self._write_setitem(i, item)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1402, in _write_setitem<br class="">INTERNALERROR>     self._save(value)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/execnet/gateway_base.py", line 1329, in _save<br class="">INTERNALERROR>     raise DumpError("can't serialize %s" % (tp,))<br class="">INTERNALERROR> DumpError: can't serialize <class 'pytest_html.URL'><br class=""><br class="">INTERNALERROR> Traceback (most recent call last):<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/main.py", line 84, in wrap_session<br class="">INTERNALERROR>     doit(config, session)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/main.py", line 122, in _main<br class="">INTERNALERROR>     config.hook.pytest_runtestloop(session=session)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 521, in __call__<br class="">INTERNALERROR>     return self._docall(self.methods, kwargs)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 528, in _docall<br class="">INTERNALERROR>     firstresult=self.firstresult).execute()<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/pytest-2.7.0-py2.7.egg/_pytest/core.py", line 394, in execute<br class="">INTERNALERROR>     res = method(*args)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/xdist/dsession.py", line 504, in pytest_runtestloop<br class="">INTERNALERROR>     self.loop_once()<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/xdist/dsession.py", line 522, in loop_once<br class="">INTERNALERROR>     call(**kwargs)<br class="">INTERNALERROR>   File "/Users/dhunt/.virtualenvs/tmp-97b1b20a17ffb8d0/lib/python2.7/site-packages/xdist/dsession.py", line 560, in slave_slavefinished<br class="">INTERNALERROR>     assert not crashitem, (crashitem, node)<br class="">INTERNALERROR> AssertionError: ('test_login.py::TestLogin::()::test_invalid_username', <SlaveController gw0>)<br class=""><br class="">--<br class="">Dave Hunt<br class="">Firefox OS Automation Engineer<br class="">Mozilla Corporation<br class="">dhunt@mozilla.com<br class=""><br class=""><blockquote type="cite" class="">On 15 Apr 2015, at 21:16, Bruno Oliveira <nicoddemus@gmail.com> wrote:<br class=""><br class="">Hi Dave,<br class=""><br class="">Congratulations on this initiative to separate this functionality into a separate plugin, it seems very useful! :)<br class=""><br class="">One way to allow other plugins to interact with yours is by defining your own hooks. Pytest-xdist does this[1], and as an example, the builtin hook pytest_report_header[2] seems to do something similar to what you want, in the sense that it allows other plugins to add information to the terminal header.<br class=""><br class="">Perhaps you can declare a hook `pytest_html_report_environment`, which plugins can implement and return a dict of environment variables to be added to the report? Or perhaps, if it makes sense for the environment details to appear in the terminal output as well, you could in fact just call `pytest_report_header` and add its contents into the HTML; the latter has the benefit that existing plugins which already use `pytest_report_header` will be able to write their information to the HTML report.<br class=""><br class="">Cheers,<br class=""><br class="">[1] https://bitbucket.org/pytest-dev/pytest-xdist/src/00cfff4834e718fd3c1ccec40811e734d796f631/xdist/newhooks.py <https://bitbucket.org/pytest-dev/pytest-xdist/src/00cfff4834e718fd3c1ccec40811e734d796f631/xdist/newhooks.py><br class="">[2] http://pytest.org/latest/example/simple.html?highlight=pytest_report_header#adding-info-to-test-report-header <http://pytest.org/latest/example/simple.html?highlight=pytest_report_header#adding-info-to-test-report-header><br class=""><br class="">On Wed, Apr 15, 2015 at 12:05 PM, Dave Hunt <dhunt@mozilla.com <mailto:dhunt@mozilla.com>> wrote:<br class="">Hey py.testers!<br class=""><br class="">I’ve been working on pulling a feature out of our pytest-mozwebqa plugin into a standalone plugin. I think others may find it useful, and it would simplify maintenance of the former plugin to split this out. Please take a look over the pytest-html plugin, the source code is available here: https://github.com/davehunt/pytest-html <https://github.com/davehunt/pytest-html><br class=""><br class="">Basically this plugin provides a new command line option of —html which allows the user to specify a path for a HTML report to be generated. The report can then be enhanced by adding extra components via  the pytest_runtest_makereport hook. You can see an example of this in my in-progress branch of pytest-mozwebqa where I’ve switched to using the new plugin: https://github.com/davehunt/pytest-mozwebqa/blob/1074f0770a146cff3108191a2fe239d15cfd92e4/pytest_mozwebqa/pytest_mozwebqa.py#L126 <https://github.com/davehunt/pytest-mozwebqa/blob/1074f0770a146cff3108191a2fe239d15cfd92e4/pytest_mozwebqa/pytest_mozwebqa.py#L126><br class=""><br class="">What I’d like some help with is providing the HTML report with environment details. This is essentially just a dictionary that will be included in the HTML report, but should be optionally provided by another plugin or conftest.py file. At the moment I accept an environment keyword argument when instantiating the HTMLReport object, but I’m not aware of a way to influence this from another plugin. See: https://github.com/davehunt/pytest-html/blob/752f229b990c80e66195374a4ed4fe22b98017c6/pytest_html.py#L44 <https://github.com/davehunt/pytest-html/blob/752f229b990c80e66195374a4ed4fe22b98017c6/pytest_html.py#L44> and https://github.com/davehunt/pytest-html/blob/752f229b990c80e66195374a4ed4fe22b98017c6/pytest_html.py#L195 <https://github.com/davehunt/pytest-html/blob/752f229b990c80e66195374a4ed4fe22b98017c6/pytest_html.py#L195><br class=""><br class="">If anybody has any advice it would be much appreciated!<br class=""><br class="">Thanks in advance,<br class=""><br class="">--<br class="">Dave Hunt<br class="">Automation Engineer<br class="">Mozilla Corporation<br class="">dhunt@mozilla.com <mailto:dhunt@mozilla.com><br class=""><br class="">_______________________________________________<br class="">pytest-dev mailing list<br class="">pytest-dev@python.org <mailto:pytest-dev@python.org><br class="">https://mail.python.org/mailman/listinfo/pytest-dev <https://mail.python.org/mailman/listinfo/pytest-dev><br class=""><br class=""><br class=""></blockquote><br class=""></blockquote><br class=""><blockquote type="cite" class="">_______________________________________________<br class="">pytest-dev mailing list<br class="">pytest-dev@python.org<br class="">https://mail.python.org/mailman/listinfo/pytest-dev<br class=""></blockquote><br class=""><br class="">-- <br class="">about me:    http://holgerkrekel.net/about-me/<br class="">contracting: http://merlinux.eu<br class=""></div></blockquote></div><br class=""></div></div></body></html>