Unittests Python dans Jenkins?

135

Comment faire en sorte que Jenkins exécute les cas unittest python? Est-il possible de produire une sortie XML de style JUnit à partir du package unittestintégré?

erikbwork
la source
1
Toutes les réponses supposent que vous souhaitez lancer les cas de test à partir de la ligne de commande. Mais si vous voulez exécuter les tests par programme, essayez ceci:import nose ; nose.runmodule() # aka nose.run(defaultTest=__name__)
MarkHu
1
À mon humble avis, la simple suggestion «py.test --junitxml results.xml test.py» répond le mieux à la question. 'yum install pytest' pour installer py.test. Ensuite, vous pouvez exécuter n'importe quel script python unittest et obtenir les résultats xml de
jUnit
1
@gaoithe qui répond à la partie jenkins, mais ne remplit pas l'exigence d'utiliser le module intégré unittest. Dans ce projet, c'était une exigence donnée.
erikbwork
@ erikb85 Quand je dis "exécuter n'importe quel script python unittest", je veux dire un script qui utilise le module unittest.
gaoithe

Réponses:

173

exemples de tests:

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 avec pytest

exécutez les tests avec:

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>

JUnit avec nez

exécutez les tests avec:

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 avec nose2

Vous auriez besoin d'utiliser le nose2.plugins.junitxmlplugin. Vous pouvez configurer nose2avec un fichier de configuration comme vous le feriez normalement, ou avec l' --pluginoption de ligne de commande.

exécutez les tests avec:

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

nose2-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 avec unittest-xml-reporting

Ajoutez ce qui suit à tests.py

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

exécutez les tests avec:

python tests.py

rapports de test / 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
la source
4
+1 pour la simple suggestion 'py.test --junitxml results.xml test.py'. 'yum install pytest' pour installer py.test. Ensuite, vous pouvez exécuter n'importe quel script python unittest et obtenir des résultats xml jUnit.
gaoithe
1
Si vous souhaitez utiliser unittest-xml-reporting et bénéficier de la fonctionnalité Test Discovery , vous pouvez mettre unittest.main(module=None, testRunner=xmlrunner.XMLTestRunner(output='test-reports')).
Rosberg Linhares
@RosbergLinhares pourquoi avez-vous besoin module=Noned'utiliser Test Discovery? Cela fonctionne exactement comme décrit dans la réponse unittest.main(testRunner=xmlrunner.XMLTestRunner(output='test-reports')).
acm
@RosbergLinhares, lors de la découverte des tests, les modules sont uniquement importés mais pas exécutés. Alors, comment l'une de ces solutions est-elle censée fonctionner avec la découverte? Je viens de l'essayer, rien de tout cela ne fonctionne. Ou est-ce que je manque quelque chose?
Konstantin
20

J'utiliserais le nez en second. Le reporting XML de base est maintenant intégré. Utilisez simplement l'option de ligne de commande --with-xunit et cela produira un fichier nosetests.xml. Par exemple:

nosetests --with-xunit

Ajoutez ensuite une action de post-génération «Publier le rapport de résultat du test JUnit» et remplissez le champ «XML du rapport de test» avec nosetests.xml (en supposant que vous ayez exécuté nosetests dans $ WORKSPACE).

Joshua D. Boyd
la source
11

Vous pouvez installer le package unittest-xml-reporting pour ajouter un exécuteur de test qui génère du XML dans le fichier unittest.

Nous utilisons pytest , qui a une sortie XML intégrée (c'est une option de ligne de commande).

Dans tous les cas, l'exécution des tests unitaires peut être effectuée en exécutant une commande shell.

Dave Bacher
la source
4

J'ai utilisé nos tests. Il existe des addons pour générer le XML pour Jenkins

John La Rooy
la source
3

Lorsque nous utilisons buildout, nous utilisons collective.xmltestreportpour produire une sortie XML de style JUnit, peut-être que c'est le code source ou le module lui-même pourrait être utile.

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

Exécutez-le en tant que shell depuis jenkins, vous pouvez obtenir le rapport dans pytest_unit.xml en tant qu'artefact.

Rajib Mitra
la source