diff --git a/tardis/tests/tests_slow/conftest.py b/tardis/tests/tests_slow/conftest.py index 5a8f6af7b0f..5f1f9f708e0 100644 --- a/tardis/tests/tests_slow/conftest.py +++ b/tardis/tests/tests_slow/conftest.py @@ -7,6 +7,7 @@ from astropy import units as u from tardis.tests.tests_slow.report import DokuReport +from tardis.tests.tests_slow.plot_helpers import PlotUploader def pytest_configure(config): @@ -39,6 +40,23 @@ def pytest_unconfigure(config): shutil.rmtree(config.option.tempdir) +@pytest.mark.hookwrapper +def pytest_runtest_makereport(item, call): + # execute all other hooks to obtain the report object + outcome = yield + report = outcome.get_result() + if report.when == "call": + if "plot_object" in item.fixturenames: + plot_obj = item.funcargs["plot_object"] + plot_obj.upload(report) + report.extra = plot_obj.get_extras() + + +@pytest.fixture(scope="function") +def plot_object(request): + return PlotUploader(request) + + @pytest.fixture(scope="session") def integration_tests_config(request): return request.config.option.integration_tests_config diff --git a/tardis/tests/tests_slow/plot_helpers.py b/tardis/tests/tests_slow/plot_helpers.py new file mode 100644 index 00000000000..b7efdffa58e --- /dev/null +++ b/tardis/tests/tests_slow/plot_helpers.py @@ -0,0 +1,86 @@ +import tempfile + +from pytest_html import extras +import tardis + + +thumbnail_html = """ +
+ + + +
+""" + + +class PlotUploader(object): + def __init__(self, request): + """A helper class to collect plots from integration tests and upload + them to DokuWiki. + + Parameters + ---------- + request : _pytest.python.RequestObject + + """ + self.request = request + self._plots = list() + self.plot_html = list() + self.dokuwiki_url = self.request.config.dokureport.dokuwiki_url + + def add(self, plot, name): + """Accept a plot figure and add it to ``self._plots``. + + Parameters + ---------- + plot : matplotlib.pyplot.figure + name : str + + """ + self._plots.append((plot, name)) + + def upload(self, report): + """Upload the content in self._plots to dokuwiki. + + Parameters + ---------- + report : _pytest.runner.TestReport + + """ + + for plot, name in self._plots: + plot_file = tempfile.NamedTemporaryFile(suffix=".png") + axes = plot.axes[0] + + if report.passed: + axes.text(0.8, 0.8, 'passed', transform=axes.transAxes, + bbox={'facecolor': 'green', 'alpha': 0.5, 'pad': 10}) + else: + axes.text(0.8, 0.8, 'failed', transform=axes.transAxes, + bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10}) + + plot.savefig(plot_file.name) + + self.request.config.dokureport.doku_conn.medias.add( + "plots:{0}_{1}.png".format(tardis.__githash__[0:7], name), + plot_file.name + ) + + self.plot_html.append(extras.html( + thumbnail_html.format( + dokuwiki_url=self.dokuwiki_url, + githash=tardis.__githash__[0:7], + name=name) + ) + ) + plot_file.close() + + def get_extras(self): + """Return ``self.plot_html`` which is further added into html report. + + Returns + ------- + list + List of strings containing raw html snippet to embed images. + """ + return self.plot_html diff --git a/tardis/tests/tests_slow/report.py b/tardis/tests/tests_slow/report.py index 757b96bfa56..3a0f3eae6ab 100644 --- a/tardis/tests/tests_slow/report.py +++ b/tardis/tests/tests_slow/report.py @@ -145,6 +145,11 @@ def _generate_report(self, session): ) ) report_content += doc.unicode(indent=2) + + # Quick hack for preventing log to be placed in narrow left out space + report_content = report_content.replace( + u'class="log"', u'class="log" style="clear: both"' + ) return report_content def _save_report(self, report_content): @@ -187,7 +192,6 @@ def pytest_terminal_summary(self, terminalreporter): self.dokuwiki_url, tardis.__githash__[0:7] ) ) - else: terminalreporter.write_sep( "-", "Connection not established, upload failed.") diff --git a/tardis/tests/tests_slow/test_w7.py b/tardis/tests/tests_slow/test_w7.py index cb1580a807f..db612530072 100644 --- a/tardis/tests/tests_slow/test_w7.py +++ b/tardis/tests/tests_slow/test_w7.py @@ -111,36 +111,33 @@ def test_luminosity_inner(self): self.reference['luminosity_inner'], self.result.luminosity_inner) - def test_spectrum(self): - try: - assert_quantity_allclose( - self.reference['luminosity_density_nu'], - self.result.runner.spectrum.luminosity_density_nu) - - assert_quantity_allclose( - self.reference['delta_frequency'], - self.result.runner.spectrum.delta_frequency) - - assert_quantity_allclose( - self.reference['wavelength'], - self.result.runner.spectrum.wavelength) - - assert_quantity_allclose( - self.reference['luminosity_density_lambda'], - self.result.runner.spectrum.luminosity_density_lambda) - - self.plot_spectrum(has_passed=True) - except Exception as e: - self.plot_spectrum(has_passed=False) - raise e - - def plot_spectrum(self, has_passed): + def test_spectrum(self, plot_object): + plot_object.add(self.plot_spectrum(), "spectrum") + + assert_quantity_allclose( + self.reference['luminosity_density_nu'], + self.result.runner.spectrum.luminosity_density_nu) + + assert_quantity_allclose( + self.reference['delta_frequency'], + self.result.runner.spectrum.delta_frequency) + + assert_quantity_allclose( + self.reference['wavelength'], + self.result.runner.spectrum.wavelength) + + assert_quantity_allclose( + self.reference['luminosity_density_lambda'], + self.result.runner.spectrum.luminosity_density_lambda) + + def plot_spectrum(self): plt.suptitle("Deviation in spectrum_quantities", fontweight="bold") + figure = plt.figure() # `ldl_` prefixed variables associated with `luminosity_density_lambda`. # Axes of subplot are extracted, if we wish to make multiple plots # for different spectrum quantities all in one figure. - ldl_ax = plt.subplot(111) + ldl_ax = figure.add_subplot(111) ldl_ax.set_title("Deviation in luminosity_density_lambda") ldl_ax.set_xlabel("Wavelength") ldl_ax.set_ylabel("Relative error (1 - result / reference)") @@ -148,20 +145,10 @@ def plot_spectrum(self, has_passed): self.result.runner.spectrum.luminosity_density_lambda.value / self.reference['luminosity_density_lambda'].value) - if has_passed: - ldl_ax.text(0.8, 0.8, 'passed', transform=ldl_ax.transAxes, - bbox={'facecolor': 'green', 'alpha': 0.5, 'pad': 10}) - ldl_ax.plot(self.reference['wavelength'], deviation, - color="green", marker=".") - else: - ldl_ax.text(0.8, 0.8, 'failed', transform=ldl_ax.transAxes, - bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10}) - ldl_ax.plot(self.reference['wavelength'], deviation, - color="red", marker=".") - - # Figure is saved in `tmp` directory right now, till a suitable way of - # saving them is decided. - plt.savefig(os.path.join(self.base_plot_dir, "spectrum.png")) + ldl_ax.plot(self.reference['wavelength'], deviation, + color="blue", marker=".") + + return figure def test_montecarlo_properties(self): assert_quantity_allclose( @@ -176,7 +163,34 @@ def test_montecarlo_properties(self): self.reference['montecarlo_nu'], self.result.montecarlo_nu) - def test_shell_temperature(self): + def test_shell_temperature(self, plot_object): + plot_object.add(self.plot_t_rads(), "t_rads") + assert_quantity_allclose( - self.reference['t_rads'], - self.result.t_rads) + self.reference['t_rads'], + self.result.t_rads) + + def plot_t_rads(self): + plt.suptitle("Shell temperature for packets", fontweight="bold") + figure = plt.figure() + + ax = figure.add_subplot(111) + ax.set_xlabel("Shell id") + ax.set_ylabel("t_rads") + + result_line = ax.plot(self.result.t_rads, color="blue", + marker=".", label="Result") + reference_line = ax.plot(self.reference['t_rads'], color="green", + marker=".", label="Reference") + ax.axis([0, 28, 5000, 10000]) + + error_ax = ax.twinx() + error_line = error_ax.plot((1 - self.result.t_rads / self.reference['t_rads']), + color="red", marker=".", label="Rel. Error") + error_ax.set_ylabel("Relative error (1 - result / reference)") + + lines = result_line + reference_line + error_line + labels = [l.get_label() for l in lines] + + ax.legend(lines, labels, loc="lower left") + return figure