<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 Bruno, the custom hook works well. Here’s the change: <a href="https://github.com/davehunt/pytest-html/commit/2a405a3cdc638c1896ab3d1074296496bb1fa3a8" class="">https://github.com/davehunt/pytest-html/commit/2a405a3cdc638c1896ab3d1074296496bb1fa3a8</a><div class=""><br class=""></div><div 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:</div><div class=""><br class=""></div><div 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=""><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=""><br class="Apple-interchange-newline">--</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=""><a href="mailto:dhunt@mozilla.com" class="">dhunt@mozilla.com</a></div></div>
</div>
<br class=""><div><blockquote type="cite" class=""><div class="">On 15 Apr 2015, at 21:16, Bruno Oliveira <<a href="mailto:nicoddemus@gmail.com" class="">nicoddemus@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Hi Dave,<div class=""><br class=""></div><div class="">Congratulations on this initiative to separate this functionality into a separate plugin, it seems very useful! :)</div><div class=""><br class=""></div><div 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.</div><div class=""><br class=""></div><div 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.</div><div class=""><br class=""></div><div class="">Cheers,</div><div class=""><br class=""></div><div class="">[1] <a href="https://bitbucket.org/pytest-dev/pytest-xdist/src/00cfff4834e718fd3c1ccec40811e734d796f631/xdist/newhooks.py" class="">https://bitbucket.org/pytest-dev/pytest-xdist/src/00cfff4834e718fd3c1ccec40811e734d796f631/xdist/newhooks.py</a><br class=""></div><div class="">[2] <a href="http://pytest.org/latest/example/simple.html?highlight=pytest_report_header#adding-info-to-test-report-header" class="">http://pytest.org/latest/example/simple.html?highlight=pytest_report_header#adding-info-to-test-report-header</a></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Wed, Apr 15, 2015 at 12:05 PM, Dave Hunt <span dir="ltr" class=""><<a href="mailto:dhunt@mozilla.com" target="_blank" class="">dhunt@mozilla.com</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="">Hey py.testers!<div class=""><br class=""></div><div 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: <a href="https://github.com/davehunt/pytest-html" target="_blank" class="">https://github.com/davehunt/pytest-html</a></div><div class=""><br class=""></div><div 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: <a href="https://github.com/davehunt/pytest-mozwebqa/blob/1074f0770a146cff3108191a2fe239d15cfd92e4/pytest_mozwebqa/pytest_mozwebqa.py#L126" target="_blank" class="">https://github.com/davehunt/pytest-mozwebqa/blob/1074f0770a146cff3108191a2fe239d15cfd92e4/pytest_mozwebqa/pytest_mozwebqa.py#L126</a></div><div class=""><br class=""></div><div 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: <a href="https://github.com/davehunt/pytest-html/blob/752f229b990c80e66195374a4ed4fe22b98017c6/pytest_html.py#L44" target="_blank" class="">https://github.com/davehunt/pytest-html/blob/752f229b990c80e66195374a4ed4fe22b98017c6/pytest_html.py#L44</a> and <a href="https://github.com/davehunt/pytest-html/blob/752f229b990c80e66195374a4ed4fe22b98017c6/pytest_html.py#L195" target="_blank" class="">https://github.com/davehunt/pytest-html/blob/752f229b990c80e66195374a4ed4fe22b98017c6/pytest_html.py#L195</a></div><div class=""><br class=""></div><div class="">If anybody has any advice it would be much appreciated!</div><div class=""><br class=""></div><div class="">Thanks in advance,<br class=""><div class="">
<div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" class=""><br class="">--</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" class=""><strong class="">Dave Hunt</strong></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" class=""><div class="">Automation Engineer<br class="">Mozilla Corporation<br class=""><a href="mailto:dhunt@mozilla.com" target="_blank" class="">dhunt@mozilla.com</a></div></div>
</div>
<br class=""></div></div><br class="">_______________________________________________<br class="">
pytest-dev mailing list<br class="">
<a href="mailto:pytest-dev@python.org" class="">pytest-dev@python.org</a><br class="">
<a href="https://mail.python.org/mailman/listinfo/pytest-dev" target="_blank" class="">https://mail.python.org/mailman/listinfo/pytest-dev</a><br class="">
<br class=""></blockquote></div><br class=""></div>
</div></blockquote></div><br class=""></div></body></html>