Python-Unittests in Jenkins?

135

Wie bringt man Jenkins dazu, Python-Unittest-Fälle auszuführen? Ist es möglich, XML-Ausgaben im JUnit-Stil aus dem integrierten unittestPaket zu erstellen?

erikbwork
quelle
1
Alle Antworten setzen voraus, dass Sie die Testfälle über die Befehlszeile initiieren möchten. Aber wenn Sie die Tests programmgesteuert ausführen möchten, versuchen Sie import nose ; nose.runmodule() # aka nose.run(defaultTest=__name__)
Folgendes
1
IMHO beantwortet der einfache Vorschlag 'py.test --junitxml results.xml test.py' die Frage am besten. 'yum install pytest', um py.test zu installieren. Dann können Sie jedes unittest Python-Skript ausführen und jUnit xml-Ergebnisse erhalten
gaoithe
1
@gaoithe, das den Jenkins-Teil beantwortet, aber nicht die Anforderung erfüllt, das eingebaute unittest-Modul zu verwenden. In diesem Projekt war es eine gegebene Anforderung.
Erikbwork
@ erikb85 Wenn ich sage "Führe ein unittest Python-Skript aus", meine ich ein Skript, das das unittest-Modul verwendet.
Gaoithe

Antworten:

173

Beispieltests:

tests.py:

# tests.py

import random
try:
    import unittest2 as unittest
except ImportError:
    import unittest

class SimpleTest(unittest.TestCase):
    @unittest.skip("demonstrating skipping")
    def test_skipped(self):
        self.fail("shouldn't happen")

    def test_pass(self):
        self.assertEqual(10, 7 + 3)

    def test_fail(self):
        self.assertEqual(11, 7 + 3)

JUnit mit Pytest

Führen Sie die Tests aus mit:

py.test --junitxml results.xml tests.py

results.xml:

<?xml version="1.0" encoding="utf-8"?>
<testsuite errors="0" failures="1" name="pytest" skips="1" tests="2" time="0.097">
    <testcase classname="tests.SimpleTest" name="test_fail" time="0.000301837921143">
        <failure message="test failure">self = &lt;tests.SimpleTest testMethod=test_fail&gt;

    def test_fail(self):
&gt;       self.assertEqual(11, 7 + 3)
E       AssertionError: 11 != 10

tests.py:16: AssertionError</failure>
    </testcase>
    <testcase classname="tests.SimpleTest" name="test_pass" time="0.000109910964966"/>
    <testcase classname="tests.SimpleTest" name="test_skipped" time="0.000164031982422">
        <skipped message="demonstrating skipping" type="pytest.skip">/home/damien/test-env/lib/python2.6/site-packages/_pytest/unittest.py:119: Skipped: demonstrating skipping</skipped>
    </testcase>
</testsuite>

Einheit mit Nase

Führen Sie die Tests aus mit:

nosetests --with-xunit

nosetests.xml:

<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="nosetests" tests="3" errors="0" failures="1" skip="1">
    <testcase classname="tests.SimpleTest" name="test_fail" time="0.000">
        <failure type="exceptions.AssertionError" message="11 != 10">
            <![CDATA[Traceback (most recent call last):
File "/opt/python-2.6.1/lib/python2.6/site-packages/unittest2-0.5.1-py2.6.egg/unittest2/case.py", line 340, in run
testMethod()
File "/home/damien/tests.py", line 16, in test_fail
self.assertEqual(11, 7 + 3)
File "/opt/python-2.6.1/lib/python2.6/site-packages/unittest2-0.5.1-py2.6.egg/unittest2/case.py", line 521, in assertEqual
assertion_func(first, second, msg=msg)
File "/opt/python-2.6.1/lib/python2.6/site-packages/unittest2-0.5.1-py2.6.egg/unittest2/case.py", line 514, in _baseAssertEqual
raise self.failureException(msg)
AssertionError: 11 != 10
]]>
        </failure>
    </testcase>
    <testcase classname="tests.SimpleTest" name="test_pass" time="0.000"></testcase>
    <testcase classname="tests.SimpleTest" name="test_skipped" time="0.000">
        <skipped type="nose.plugins.skip.SkipTest" message="demonstrating skipping">
            <![CDATA[SkipTest: demonstrating skipping
]]>
        </skipped>
    </testcase>
</testsuite>

JUnit mit Nase2

Sie müssten das nose2.plugins.junitxmlPlugin verwenden. Sie können nose2mit einer Konfigurationsdatei konfigurieren, wie Sie es normalerweise tun würden, oder mit der --pluginBefehlszeilenoption.

Führen Sie die Tests aus mit:

nose2 --plugin nose2.plugins.junitxml --junit-xml tests

nas2-junit.xml:

<testsuite errors="0" failures="1" name="nose2-junit" skips="1" tests="3" time="0.001">
  <testcase classname="tests.SimpleTest" name="test_fail" time="0.000126">
    <failure message="test failure">Traceback (most recent call last):
  File "/Users/damien/Work/test2/tests.py", line 18, in test_fail
    self.assertEqual(11, 7 + 3)
AssertionError: 11 != 10
</failure>
  </testcase>
  <testcase classname="tests.SimpleTest" name="test_pass" time="0.000095" />
  <testcase classname="tests.SimpleTest" name="test_skipped" time="0.000058">
    <skipped />
  </testcase>
</testsuite>

JUnit mit unittest-xml-Reporting

Fügen Sie Folgendes hinzu: tests.py

if __name__ == '__main__':
    import xmlrunner
    unittest.main(testRunner=xmlrunner.XMLTestRunner(output='test-reports'))

Führen Sie die Tests aus mit:

python tests.py

Testberichte / TEST-SimpleTest-20131001140629.xml:

<?xml version="1.0" ?>
<testsuite errors="1" failures="0" name="SimpleTest-20131001140629" tests="3" time="0.000">
    <testcase classname="SimpleTest" name="test_pass" time="0.000"/>
    <testcase classname="SimpleTest" name="test_fail" time="0.000">
        <error message="11 != 10" type="AssertionError">
<![CDATA[Traceback (most recent call last):
  File "tests.py", line 16, in test_fail
    self.assertEqual(11, 7 + 3)
AssertionError: 11 != 10
]]>     </error>
    </testcase>
    <testcase classname="SimpleTest" name="test_skipped" time="0.000">
        <skipped message="demonstrating skipping" type="skip"/>
    </testcase>
    <system-out>
<![CDATA[]]>    </system-out>
    <system-err>
<![CDATA[]]>    </system-err>
</testsuite>
dnozay
quelle
4
+1 für den einfachen Vorschlag 'py.test --junitxml results.xml test.py'. 'yum install pytest', um py.test zu installieren. Dann können Sie jedes unittest Python-Skript ausführen und jUnit xml-Ergebnisse erhalten.
Gaoithe
1
Wenn Sie unittest-xml-reporting verwenden und von der Test Discovery-Funktion profitieren möchten , können Sie dies tun unittest.main(module=None, testRunner=xmlrunner.XMLTestRunner(output='test-reports')).
Rosberg Linhares
@RosbergLinhares Warum müssen Sie module=NoneTest Discovery verwenden? Es funktioniert genau wie in der Antwort beschrieben unittest.main(testRunner=xmlrunner.XMLTestRunner(output='test-reports')).
Acm
@RosbergLinhares, während der Testerkennung werden die Module nur importiert, aber nicht ausgeführt. Wie soll eine dieser Lösungen mit Discovery funktionieren? Ich habe es gerade ausprobiert, nichts davon funktioniert. Oder fehlt mir etwas?
Konstantin
20

Ich würde zweitens die Nase benutzen. Die grundlegende XML-Berichterstellung ist jetzt integriert. Verwenden Sie einfach die Befehlszeilenoption --with-xunit, um eine Datei nosetests.xml zu erstellen. Beispielsweise:

Nasentests - mit Xunit

Fügen Sie dann nach dem Erstellen eine Aktion "JUnit-Testergebnisbericht veröffentlichen" hinzu und füllen Sie das Feld "XMLs für Testberichte" mit nosetests.xml aus (vorausgesetzt, Sie haben Nosetests in $ WORKSPACE ausgeführt).

Joshua D. Boyd
quelle
11

Sie können das unittest-xml-Berichtspaket installieren , um einen Testläufer hinzuzufügen, der dem integrierten XML generiert unittest.

Wir verwenden pytest , in das eine XML-Ausgabe integriert ist (eine Befehlszeilenoption).

In beiden Fällen kann die Ausführung der Komponententests durch Ausführen eines Shell-Befehls erfolgen.

Dave Bacher
quelle
4

Ich habe Nasentests verwendet. Es gibt Addons zum Ausgeben des XML für Jenkins

John La Rooy
quelle
3

Bei Verwendung von Buildout verwenden wir collective.xmltestreportXML-Ausgaben im JUnit-Stil. Möglicherweise ist dies der Quellcode oder das Modul selbst könnte hilfreich sein.

Martijn Pieters
quelle
2
python -m pytest --junit-xml=pytest_unit.xml source_directory/test/unit || true # tests may fail

Führen Sie dies als Shell von Jenkins aus. Sie können den Bericht in pytest_unit.xml als Artefakt abrufen.

Rajib Mitra
quelle