UnitTest Framework - Guida rapida

Il test unitario è un metodo di test del software mediante il quale vengono testate singole unità di codice sorgente, come funzioni, metodi e classi per determinare se sono adatte all'uso. Intuitivamente, è possibile visualizzare un'unità come la più piccola parte testabile di un'applicazione. Gli unit test sono brevi frammenti di codice creati dai programmatori durante il processo di sviluppo. Costituisce la base per il test dei componenti.

I test unitari possono essere eseguiti nei due modi seguenti:

Test manuale Test automatizzati

L'esecuzione manuale dei casi di test senza alcun supporto di strumenti è nota come test manuale.

  • Poiché i casi di test vengono eseguiti dalle risorse umane, è molto time consuming and tedious.

  • Poiché i casi di test devono essere eseguiti manualmente, sono necessari più tester nei test manuali.

  • È meno affidabile in quanto i test potrebbero non essere eseguiti con precisione ogni volta a causa di errori umani.

  • Non è possibile eseguire alcuna programmazione per scrivere test sofisticati che recuperano informazioni nascoste.

Il supporto dello strumento e l'esecuzione dei casi di test utilizzando lo strumento di automazione è noto come test di automazione.

  • Fast Automation esegue casi di test molto più velocemente delle risorse umane.

  • Il investment over human resources is less poiché i casi di test vengono eseguiti utilizzando lo strumento di automazione.

  • I test di automazione eseguono esattamente la stessa operazione ogni volta che vengono eseguiti e are more reliable.

  • Tester can program sophisticated tests per far emergere informazioni nascoste.

JUnit è un framework di unit test per il linguaggio di programmazione Java. JUnit è stato importante nello sviluppo dello sviluppo basato sui test ed è uno di una famiglia di framework di unit test noti collettivamente come xUnit che ha avuto origine con JUnit. Puoi trovare il tutorial di JUnit qui.

Il framework di unit test Python, a volte indicato come "PyUnit", è una versione in linguaggio Python di JUnit sviluppata da Kent Beck e Erich Gamma. PyUnit fa parte della Python Standard Library a partire dalla versione 2.1 di Python.

Il framework di unit test Python supporta l'automazione dei test, la condivisione del codice di configurazione e spegnimento per i test, l'aggregazione dei test in raccolte e l'indipendenza dei test dal framework di reporting. Il modulo unittest fornisce classi che facilitano il supporto di queste qualità per una serie di test.

Questo tutorial è stato preparato per i principianti per aiutarli a comprendere le funzionalità di base del framework di test Python. Dopo aver completato questo tutorial, ti troverai a un livello moderato di esperienza nell'uso del framework di test Python da cui puoi passare ai livelli successivi.

Dovresti avere una ragionevole esperienza nello sviluppo di software utilizzando il linguaggio Python. Il nostro tutorial su Python è un buon punto di partenza per imparare a usare Python. È auspicabile anche la conoscenza delle basi del test del software.

Configurazione dell'ambiente

Le classi necessarie per scrivere i test si trovano nel modulo 'unittest'. Se stai usando versioni precedenti di Python (precedenti a Python 2.1), il modulo può essere scaricato dahttp://pyunit.sourceforge.net/. Tuttavia, il modulo unittest ora fa parte della distribuzione standard di Python; quindi non richiede installazione separata.

"unittest" supporta l'automazione dei test, la condivisione del codice di configurazione e spegnimento per i test, l'aggregazione dei test in raccolte e l'indipendenza dei test dal framework di reporting.

Il modulo unittest fornisce classi che facilitano il supporto di queste qualità per una serie di test.

Per raggiungere questo obiettivo, unittest supporta i seguenti importanti concetti:

  • test fixture- Rappresenta la preparazione necessaria per eseguire uno o più test e qualsiasi azione di pulizia associata. Ciò può comportare, ad esempio, la creazione di directory, database temporanei o proxy o l'avvio di un processo del server.

  • test case- Questa è la più piccola unità di test. Questo verifica una risposta specifica a un particolare insieme di input. unittest fornisce una classe base,TestCase, che può essere utilizzato per creare nuovi casi di test.

  • test suite- Questa è una raccolta di casi di test, suite di test o entrambi. Viene utilizzato per aggregare i test che dovrebbero essere eseguiti insieme. Le suite di test sono implementate dalla classe TestSuite.

  • test runner- Questo è un componente che orchestra l'esecuzione dei test e fornisce il risultato all'utente. Il corridore può utilizzare un'interfaccia grafica, un'interfaccia testuale o restituire un valore speciale per indicare i risultati dell'esecuzione dei test.

Creazione di uno unit test

I seguenti passaggi sono coinvolti nella scrittura di un semplice test unitario:

Step 1 - Importa il modulo unittest nel tuo programma.

Step 2- Definire una funzione da testare. Nell'esempio seguente, la funzione add () deve essere sottoposta a test.

Step 3 - Crea un testcase sottoclassando unittest.TestCase.

Step 4- Definisci un test come metodo all'interno della classe. Il nome del metodo deve iniziare con "test".

Step 5- Ogni test chiama la funzione di asserzione della classe TestCase. Esistono molti tipi di affermazioni. L'esempio seguente chiama la funzione assertEquals ().

Step 6 - La funzione assertEquals () confronta il risultato della funzione add () con l'argomento arg2 e lancia assertionError se il confronto fallisce.

Step 7 - Infine, chiama il metodo main () dal modulo unittest.

import unittest
def add(x,y):
   return x + y
   
class SimpleTest(unittest.TestCase):
   def testadd1(self):
      self.assertEquals(add(4,5),9)
      
if __name__ == '__main__':
   unittest.main()

Step 8 - Esegui lo script precedente dalla riga di comando.

C:\Python27>python SimpleTest.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK

Step 9 - I tre seguenti potrebbero essere i possibili risultati di un test -

Suor n Messaggio e descrizione
1

OK

Il test viene superato. Sulla console viene visualizzato "A".

2

FAIL

Il test non viene superato e genera un'eccezione AssertionError. "F" viene visualizzato sulla console.

3

ERROR

Il test solleva un'eccezione diversa da AssertionError. Sulla console viene visualizzato "E".

Questi risultati vengono visualizzati sulla console rispettivamente da ".", "F" ed "E".

Interfaccia della riga di comando

Il modulo unittest può essere utilizzato dalla riga di comando per eseguire test singoli o multipli.

python -m unittest test1
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method

unittest supporta le seguenti opzioni della riga di comando. Per un elenco di tutte le opzioni della riga di comando, utilizzare il seguente comando:

Python –m unittest -h

Suor n Opzione e descrizione
1

-h, --help

Mostra questo messaggio

2

v, --verbose

Output dettagliato

3

-q, --quiet

Produzione minima

4

-f, --failfast

Fermati al primo fallimento

5

-c, --catch

Cattura control-C e visualizza i risultati

6

-b, --buffer

Buffer stdout e stderr durante le esecuzioni di test

Questo capitolo discute le classi e i metodi definiti nel modulo unittest. Ci sono cinque classi principali in questo modulo.

Classe TestCase

L'oggetto di questa classe rappresenta la più piccola unità testabile. Contiene le routine di test e fornisce ganci per la preparazione di ogni routine e per la pulizia successiva.

I seguenti metodi sono definiti nella classe TestCase:

Suor n Metodo e descrizione
1

setUp()

Metodo chiamato per preparare il dispositivo di prova. Questo viene chiamato immediatamente prima di chiamare il metodo di test

2

tearDown()

Metodo chiamato immediatamente dopo che il metodo di prova è stato chiamato e il risultato registrato. Viene chiamato anche se il metodo di test ha sollevato un'eccezione,

3

setUpClass()

Un metodo di classe chiamato prima dei test in un'esecuzione di una singola classe.

4

tearDownClass()

Un metodo di classe chiamato dopo l'esecuzione dei test in una singola classe.

5

run(result = None)

Eseguire il test, raccogliendo il risultato nell'oggetto risultato del test passato come risultato .

6

skipTest(reason)

Chiamarlo durante un metodo di test o setUp () salta il test corrente.

7

debug()

Esegui il test senza raccogliere il risultato.

8

shortDescription()

Restituisce una descrizione di una riga del test.

Infissi

Ci possono essere numerosi test scritti all'interno di una classe TestCase. Questi metodi di test potrebbero richiedere la connessione al database, i file temporanei o altre risorse per essere inizializzati. Questi sono chiamati infissi. TestCase include un gancio speciale per configurare e pulire tutti i dispositivi necessari per i tuoi test. Per configurare i fari, sovrascrivere setUp (). Per ripulire, sovrascrivi tearDown ().

Nell'esempio seguente, due test vengono scritti all'interno della classe TestCase. Testano il risultato dell'addizione e della sottrazione di due valori. Il metodo setup () inizializza gli argomenti in base a shortDescription () di ogni test. Il metodo teardown () verrà eseguito alla fine di ogni test.

import unittest

class simpleTest2(unittest.TestCase):
   def setUp(self):
      self.a = 10
      self.b = 20
      name = self.shortDescription()
      if name == "Add":
         self.a = 10
         self.b = 20
         print name, self.a, self.b
      if name == "sub":
         self.a = 50
         self.b = 60
         print name, self.a, self.b
   def tearDown(self):
      print '\nend of test',self.shortDescription()

   def testadd(self):
      """Add"""
      result = self.a+self.b
      self.assertTrue(result == 100)
   def testsub(self):
      """sub"""
      result = self.a-self.b
      self.assertTrue(result == -10)
      
if __name__ == '__main__':
   unittest.main()

Esegui il codice sopra dalla riga di comando. Fornisce il seguente output:

C:\Python27>python test2.py
Add 10 20
F
end of test Add
sub 50 60
end of test sub
.
================================================================
FAIL: testadd (__main__.simpleTest2)
Add
----------------------------------------------------------------------
Traceback (most recent call last):
   File "test2.py", line 21, in testadd
      self.assertTrue(result == 100)
AssertionError: False is not true
----------------------------------------------------------------------
Ran 2 tests in 0.015s

FAILED (failures = 1)

Apparecchio di classe

La classe TestCase ha un metodo setUpClass () che può essere sovrascritto per essere eseguito prima dell'esecuzione dei singoli test all'interno di una classe TestCase. Allo stesso modo, il metodo tearDownClass () verrà eseguito dopo tutti i test nella classe. Entrambi i metodi sono metodi di classe. Quindi, devono essere decorati con la direttiva @classmethod.

Il seguente esempio dimostra l'uso di questi metodi di classe:

import unittest

class TestFixtures(unittest.TestCase):

   @classmethod
   def setUpClass(cls):
      print 'called once before any tests in class'

   @classmethod
   def tearDownClass(cls):
      print '\ncalled once after all tests in class'

   def setUp(self):
      self.a = 10
      self.b = 20
      name = self.shortDescription()
      print '\n',name
   def tearDown(self):
      print '\nend of test',self.shortDescription()

   def test1(self):
      """One"""
      result = self.a+self.b
      self.assertTrue(True)
   def test2(self):
      """Two"""
      result = self.a-self.b
      self.assertTrue(False)
      
if __name__ == '__main__':
unittest.main()

Classe TestSuite

Il framework di test di Python fornisce un meccanismo utile mediante il quale le istanze dei casi di test possono essere raggruppate in base alle funzionalità che testano. Questo meccanismo è reso disponibile dalla classe TestSuite nel modulo unittest.

I seguenti passaggi sono coinvolti nella creazione e nell'esecuzione di una suite di test.

Step 1 - Crea un'istanza della classe TestSuite.

suite = unittest.TestSuite()

Step 2 - Aggiungi test all'interno di una classe TestCase nella suite.

suite.addTest(testcase class)

Step 3 - Puoi anche usare il metodo makeSuite () per aggiungere test da una classe

suite = unittest.makeSuite(test case class)

Step 4 - È anche possibile aggiungere test individuali nella suite.

suite.addTest(testcaseclass(""testmethod")

Step 5 - Crea un oggetto della classe TestTestRunner.

runner = unittest.TextTestRunner()

Step 6 - Chiama il metodo run () per eseguire tutti i test nella suite

runner.run (suite)

I seguenti metodi sono definiti nella classe TestSuite:

Suor n Metodo e descrizione
1

addTest()

Aggiunge un metodo di test nella suite di test.

2

addTests()

Aggiunge test da più classi TestCase.

3

run()

Esegue i test associati a questa suite, raccogliendo il risultato nell'oggetto risultato del test

4

debug()

Esegue i test associati a questa suite senza raccogliere il risultato.

5

countTestCases()

Restituisce il numero di test rappresentati da questo oggetto di test

L'esempio seguente mostra come utilizzare la classe TestSuite:

import unittest
class suiteTest(unittest.TestCase):
   def setUp(self):
      self.a = 10
      self.b = 20
      
   def testadd(self):
      """Add"""
      result = self.a+self.b
      self.assertTrue(result == 100)
   def testsub(self):
      """sub"""
      result = self.a-self.b
      self.assertTrue(result == -10)
      
def suite():
   suite = unittest.TestSuite()
##   suite.addTest (simpleTest3("testadd"))
##   suite.addTest (simpleTest3("testsub"))
   suite.addTest(unittest.makeSuite(simpleTest3))
   return suite
   
if __name__ == '__main__':
   runner = unittest.TextTestRunner()
   test_suite = suite()
   runner.run (test_suite)

È possibile sperimentare con il metodo addTest () decommentando le righe e la dichiarazione di commento con il metodo makeSuite ().

Classe TestLoader

Il pacchetto unittest ha la classe TestLoader che viene utilizzata per creare suite di test da classi e moduli. Per impostazione predefinita, l'istanza unittest.defaultTestLoader viene creata automaticamente quando viene chiamato il metodo unittest.main (0. Un'istanza esplicita, tuttavia, consente la personalizzazione di alcune proprietà.

Nel codice seguente, i test di due classi vengono raccolti in un elenco utilizzando l'oggetto TestLoader.

import unittest
testList = [Test1, Test2]
testLoad = unittest.TestLoader()

TestList = []
for testCase in testList:
   testSuite = testLoad.loadTestsFromTestCase(testCase)
   TestList.append(testSuite)
   
newSuite = unittest.TestSuite(TestList)
runner = unittest.TextTestRunner()
runner.run(newSuite)

La tabella seguente mostra un elenco di metodi nella classe TestLoader -

S.No Metodo e descrizione
1

loadTestsFromTestCase()

Restituisce una suite di tutti i casi di test contenuti in una classe TestCase

2

loadTestsFromModule()

Restituisce una suite di tutti i casi di test contenuti nel modulo dato.

3

loadTestsFromName()

Restituisce una suite di tutti i casi di test dato uno specificatore di stringa.

4

discover()

Trova tutti i moduli di test ricorrendo nelle sottodirectory dalla directory di avvio specificata e restituisci un oggetto TestSuite

Classe TestResult

Questa classe viene utilizzata per compilare informazioni sui test che hanno avuto esito positivo e sui test che hanno avuto esito negativo. Un oggetto TestResult archivia i risultati di una serie di test. Un'istanza TestResult viene restituita dal metodo TestRunner.run ().

Le istanze di TestResult hanno i seguenti attributi:

Suor n Attributo e descrizione
1

Errors

Un elenco contenente 2 tuple di istanze di TestCase e stringhe contenenti traceback formattati. Ogni tupla rappresenta un test che ha sollevato un'eccezione imprevista.

2

Failures

Un elenco contenente 2 tuple di istanze di TestCase e stringhe contenenti traceback formattati. Ogni tupla rappresenta un test in cui un errore è stato esplicitamente segnalato utilizzando i metodi TestCase.assert * ().

3

Skipped

Un elenco contenente 2 tuple di istanze di TestCase e stringhe contenenti il ​​motivo per cui si è saltato il test.

4

wasSuccessful()

Restituisce True se tutti i test eseguiti finora sono stati superati, altrimenti restituisce False.

5

stop()

Questo metodo può essere chiamato per segnalare che il set di test in esecuzione deve essere interrotto.

6

startTestRun()

Chiamato una volta prima dell'esecuzione di qualsiasi test.

7

stopTestRun()

Chiamato una volta dopo che tutti i test sono stati eseguiti.

8

testsRun

Il numero totale di test eseguiti finora.

9

Buffer

Se impostato su true, sys.stdout e sys.stderr verrà memorizzato nel buffer tra startTest () e stopTest () in fase di chiamata.

Il codice seguente esegue una suite di test:

if __name__ == '__main__':
   runner = unittest.TextTestRunner()
   test_suite = suite()
   result = runner.run (test_suite)
   
   print "---- START OF TEST RESULTS"
   print result

   print "result::errors"
   print result.errors

   print "result::failures"
   print result.failures

   print "result::skipped"
   print result.skipped

   print "result::successful"
   print result.wasSuccessful()
   
   print "result::test-run"
   print result.testsRun
   print "---- END OF TEST RESULTS"

Il codice quando viene eseguito mostra il seguente output:

---- START OF TEST RESULTS
<unittest.runner.TextTestResult run = 2 errors = 0 failures = 1>
result::errors
[]
result::failures
[(<__main__.suiteTest testMethod = testadd>, 'Traceback (most recent call last):\n
   File "test3.py", line 10, in testadd\n 
   self.assertTrue(result == 100)\nAssert
   ionError: False is not true\n')]
result::skipped
[]
result::successful
False
result::test-run
2
---- END OF TEST RESULTS

Il framework di test Python utilizza la funzione assert () incorporata di Python che verifica una particolare condizione. Se l'asserzione fallisce, verrà sollevata un'eccezione AssertionError. Il framework di test identificherà quindi il test come Fallimento. Altre eccezioni vengono trattate come Errore.

I seguenti tre set di funzioni di asserzione sono definiti nel modulo unittest:

  • Asserzioni booleane di base
  • Affermazioni comparative
  • Afferma per le raccolte

Le funzioni di asserzione di base valutano se il risultato di un'operazione è Vero o Falso. Tutti i metodi di asserzione accettano amsg argomento che, se specificato, viene utilizzato come messaggio di errore in caso di fallimento.

Suor n Metodo e descrizione
1

assertEqual(arg1, arg2, msg = None)

Verifica che arg1 e arg2 siano uguali. Se i valori non sono uguali, il test fallirà.

2

assertNotEqual(arg1, arg2, msg = None)

Verifica che arg1 e arg2 non siano uguali. Se i valori sono uguali, il test fallirà.

3

assertTrue(expr, msg = None)

Verifica che expr sia vero. Se falso, il test fallisce

4

assertFalse(expr, msg = None)

Verifica che espr sia falso. Se è vero, il test fallisce

5

assertIs(arg1, arg2, msg = None)

Verifica che arg1 e arg2 valutino lo stesso oggetto.

6

assertIsNot(arg1, arg2, msg = None)

Verifica che arg1 e arg2 non restituiscano lo stesso oggetto.

7

assertIsNone(expr, msg = None)

Verifica che espr sia Nessuno. Se non è Nessuno, il test fallisce

8

assertIsNotNone(expr, msg = None)

Verifica che expr non sia None. Se Nessuno, il test fallisce

9

assertIn(arg1, arg2, msg = None)

Verifica che arg1 sia in arg2 .

10

assertNotIn(arg1, arg2, msg = None)

Verifica che arg1 non sia in arg2 .

11

assertIsInstance(obj, cls, msg = None)

Verifica che obj sia un'istanza di cls

12

assertNotIsInstance(obj, cls, msg = None)

Verifica che obj non sia un'istanza di cls

Alcune delle funzioni di asserzione di cui sopra sono implementate nel codice seguente:

import unittest

class SimpleTest(unittest.TestCase):
   def test1(self):
      self.assertEqual(4 + 5,9)
   def test2(self):
      self.assertNotEqual(5 * 2,10)
   def test3(self):
      self.assertTrue(4 + 5 == 9,"The result is False")
   def test4(self):
      self.assertTrue(4 + 5 == 10,"assertion fails")
   def test5(self):
      self.assertIn(3,[1,2,3])
   def test6(self):
      self.assertNotIn(3, range(5))

if __name__ == '__main__':
   unittest.main()

Quando lo script precedente viene eseguito, test2, test4 e test6 mostreranno un errore e altri verranno eseguiti correttamente.

FAIL: test2 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python27\SimpleTest.py", line 9, in test2
      self.assertNotEqual(5*2,10)
AssertionError: 10 == 10

FAIL: test4 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python27\SimpleTest.py", line 13, in test4
      self.assertTrue(4+5==10,"assertion fails")
AssertionError: assertion fails

FAIL: test6 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python27\SimpleTest.py", line 17, in test6
      self.assertNotIn(3, range(5))
AssertionError: 3 unexpectedly found in [0, 1, 2, 3, 4]

----------------------------------------------------------------------            
Ran 6 tests in 0.001s                                                             
                                                                                  
FAILED (failures = 3)

La seconda serie di funzioni di asserzione sono comparative asserts −

  • assertAlmostEqual (primo, secondo, posizioni = 7, msg = Nessuno, delta = Nessuno)

    Test che prima e seconda sono approssimativamente (o meno circa) uguale calcolando la differenza, arrotondamento al numero specificato di decimali posti (default 7),

  • assertNotAlmostEqual (primo, secondo, luoghi, msg, delta)

    Verifica che il primo e il secondo non siano approssimativamente uguali calcolando la differenza, arrotondando al numero di cifre decimali specificato (predefinito 7) e confrontando a zero.

    In entrambe le funzioni di cui sopra, se delta viene fornito al posto dei posti, la differenza tra il primo e il secondo deve essere minore o uguale a (o maggiore di) delta.

    Fornire sia delta che posti solleva un'eccezione TypeError.

  • assertGreater (primo, secondo, msg = Nessuno)

    Verificare che il primo sia maggiore del secondo a seconda del nome del metodo. In caso contrario, il test fallirà.

  • assertGreaterEqual (primo, secondo, msg = Nessuno)

    Verificare che il primo sia maggiore o uguale al secondo a seconda del nome del metodo. In caso contrario, il test fallirà

  • assertLess (primo, secondo, msg = Nessuno)

    Verifica che il primo sia inferiore al secondo a seconda del nome del metodo. In caso contrario, il test fallirà

  • assertLessEqual (primo, secondo, msg = Nessuno)

    Verificare che il primo sia minore o uguale al secondo a seconda del nome del metodo. In caso contrario, il test fallirà.

  • assertRegexpMatches (testo, regexp, msg = Nessuno)

    Verifica che una ricerca regexp corrisponda al testo. In caso di errore, il messaggio di errore includerà il modello e il testo. regexp può essere un oggetto espressione regolare o una stringa contenente un'espressione regolare adatta all'uso da parte dire.search().

  • assertNotRegexpMatches (testo, regexp, msg = Nessuno)

    Verifica che una ricerca regexp non corrisponda al testo . Non riesce con un messaggio di errore che include il modello e la parte di testo che corrisponde. regexp può essere un oggetto espressione regolare o una stringa contenente un'espressione regolare adatta all'uso da parte dire.search().

Le funzioni di asserzione sono implementate nel seguente esempio:

import unittest
import math
import re

class SimpleTest(unittest.TestCase):
   def test1(self):
      self.assertAlmostEqual(22.0/7,3.14)
   def test2(self):
      self.assertNotAlmostEqual(10.0/3,3)
   def test3(self):
      self.assertGreater(math.pi,3)
   def test4(self):
      self.assertNotRegexpMatches("Tutorials Point (I) Private Limited","Point")

if __name__ == '__main__':
   unittest.main()

Lo script precedente riporta test1 e test4 come Fallimento. In test1, la divisione di 22/7 non è entro 7 cifre decimali di 3,14. Allo stesso modo, poiché il secondo argomento corrisponde al testo nel primo argomento, test4 restituisce AssertionError.

=====================================================FAIL: test1 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 7, in test1
      self.assertAlmostEqual(22.0/7,3.14)
AssertionError: 3.142857142857143 != 3.14 within 7 places
================================================================
FAIL: test4 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 13, in test4
      self.assertNotRegexpMatches("Tutorials Point (I) Private Limited","Point")
AssertionError: Regexp matched: 'Point' matches 'Point' in 'Tutorials Point (I)
Private Limited'
----------------------------------------------------------------------

Ran 4 tests in 0.001s                                                             
                                                                                  
FAILED (failures = 2)

Affermare per le raccolte

Questo set di funzioni di asserzione è pensato per essere utilizzato con i tipi di dati di raccolta in Python, come List, Tuple, Dictionary e Set.

Suor n Metodo e descrizione
1

assertListEqual (list1, list2, msg = None)

Verifica che due elenchi siano uguali. In caso contrario, viene creato un messaggio di errore che mostra solo le differenze tra i due.

2

assertTupleEqual (tuple1, tuple2, msg = None)

Verifica che due tuple siano uguali. In caso contrario, viene creato un messaggio di errore che mostra solo le differenze tra i due.

3

assertSetEqual (set1, set2, msg = None)

Verifica che due set sono uguali. In caso contrario, viene creato un messaggio di errore che elenca le differenze tra i set.

4

assertDictEqual (expected, actual, msg = None)

Verifica che due dizionari siano uguali. In caso contrario, viene creato un messaggio di errore che mostra le differenze nei dizionari.

Il seguente esempio implementa i metodi precedenti:

import unittest

class SimpleTest(unittest.TestCase):
   def test1(self):
      self.assertListEqual([2,3,4], [1,2,3,4,5])
   def test2(self):
      self.assertTupleEqual((1*2,2*2,3*2), (2,4,6))
   def test3(self):
      self.assertDictEqual({1:11,2:22},{3:33,2:22,1:11})

if __name__ == '__main__':
   unittest.main()

Nell'esempio precedente, test1 e test3 mostrano AssertionError. Il messaggio di errore mostra le differenze tra gli oggetti List e Dictionary.

FAIL: test1 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 5, in test1
      self.assertListEqual([2,3,4], [1,2,3,4,5])
AssertionError: Lists differ: [2, 3, 4] != [1, 2, 3, 4, 5]

First differing element 0:
2
1

Second list contains 2 additional elements.
First extra element 3:
4

- [2, 3, 4]
+ [1, 2, 3, 4, 5]
? +++       +++

FAIL: test3 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 9, in test3
      self.assertDictEqual({1:11,2:22},{3:33,2:22,1:11})
AssertionError: {1: 11, 2: 22} != {1: 11, 2: 22, 3: 33}
- {1: 11, 2: 22}
+ {1: 11, 2: 22, 3: 33}
?              +++++++
                                                                                  
----------------------------------------------------------------------            
Ran 3 tests in 0.001s                                                             
                                                                                  
FAILED (failures = 2)

La classe TestLoader ha una funzione discover (). Il framework di test Python lo utilizza per una semplice scoperta di test. Per essere compatibili, moduli e pacchetti contenenti test devono essere importabili dalla directory di primo livello.

Di seguito è riportato l'utilizzo di base della riga di comando per l'individuazione dei test:

Python –m unittest discover

Interpreter cerca di caricare ricorsivamente tutti i moduli contenenti test dalla directory corrente e dalle directory interne. Altre opzioni della riga di comando sono:

Suor n Opzioni e descrizione
1

-v, --verbose

Output dettagliato

2

-s, --start-directory

directory Directory per avviare il rilevamento (. default)

3

-p, --pattern

pattern Pattern per abbinare i file di test (test * .py predefinito)

4

-t, --top-level-directory

directory Directory di primo livello del progetto (il valore predefinito è la directory iniziale)

Ad esempio, per scoprire i test nei moduli i cui nomi iniziano con 'assert' nella directory 'tests', viene utilizzata la seguente riga di comando:

C:\python27>python –m unittest –v –s "c:\test" –p "assert*.py"

Test discovery carica i test importandoli. Una volta che il rilevamento del test ha trovato tutti i file di test dalla directory iniziale specificata, trasforma i percorsi in nomi di pacchetti da importare.

Se fornisci la directory di avvio come nome di pacchetto anziché come percorso di una directory, discover presuppone che il percorso da cui importa è il percorso desiderato, quindi non riceverai l'avviso.

Il supporto per saltare i test è stato aggiunto da Python 2.7. È possibile saltare il metodo di test individuale o la classe TestCase, in modo condizionale e incondizionato. Il framework consente di contrassegnare un determinato test come "errore previsto". Questo test "fallirà" ma non verrà considerato come fallito in TestResult.

Per saltare un metodo incondizionatamente, è possibile utilizzare il seguente metodo di classe unittest.skip ():

import unittest

   def add(x,y):
      return x+y

class SimpleTest(unittest.TestCase):
   @unittest.skip("demonstrating skipping")
   def testadd1(self):
      self.assertEquals(add(4,5),9)

if __name__ == '__main__':
   unittest.main()

Poiché skip () è un metodo di classe, è preceduto da @ token. Il metodo accetta un argomento: un messaggio di log che descrive il motivo del salto.

Quando viene eseguito lo script precedente, sulla console viene visualizzato il seguente risultato:

C:\Python27>python skiptest.py
s
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK (skipped = 1)

Il carattere "s" indica che un test è stato saltato.

La sintassi alternativa per saltare il test utilizza il metodo di istanza skipTest () all'interno della funzione di test.

def testadd2(self):
   self.skipTest("another method for skipping")
   self.assertTrue(add(4 + 5) == 10)

I seguenti decoratori implementano il salto del test e gli errori previsti:

Suor n Metodo e descrizione
1

unittest.skip(reason)

Salta incondizionatamente il test decorato. il motivo dovrebbe descrivere il motivo per cui il test viene saltato.

2

unittest.skipIf(condition, reason)

Salta il test decorato se la condizione è vera.

3

unittest.skipUnless(condition, reason)

Salta il test decorato a meno che la condizione non sia vera.

4

unittest.expectedFailure()

Contrassegnare il test come un fallimento previsto. Se il test fallisce quando viene eseguito, il test non viene considerato un fallimento.

L'esempio seguente mostra l'uso del salto condizionale e del fallimento previsto.

import unittest

class suiteTest(unittest.TestCase):
   a = 50
   b = 40
   
   def testadd(self):
      """Add"""
      result = self.a+self.b
      self.assertEqual(result,100)

   @unittest.skipIf(a>b, "Skip over this routine")
   def testsub(self):
      """sub"""
      result = self.a-self.b
      self.assertTrue(result == -10)
   
   @unittest.skipUnless(b == 0, "Skip over this routine")
   def testdiv(self):
      """div"""
      result = self.a/self.b
      self.assertTrue(result == 1)

   @unittest.expectedFailure
   def testmul(self):
      """mul"""
      result = self.a*self.b
      self.assertEqual(result == 0)

if __name__ == '__main__':
   unittest.main()

Nell'esempio precedente, testsub () e testdiv () verranno ignorati. Nel primo caso a> b è vero, mentre nel secondo caso b == 0 non è vero. D'altra parte, testmul () è stato contrassegnato come errore previsto.

Quando viene eseguito lo script precedente, due test ignorati mostrano "s" e l'errore previsto viene visualizzato come "x".

C:\Python27>python skiptest.py
Fsxs
================================================================
FAIL: testadd (__main__.suiteTest)
Add
----------------------------------------------------------------------
Traceback (most recent call last):
   File "skiptest.py", line 9, in testadd
      self.assertEqual(result,100)
AssertionError: 90 != 100

----------------------------------------------------------------------
Ran 4 tests in 0.000s

FAILED (failures = 1, skipped = 2, expected failures = 1)

Il framework di test Python fornisce i seguenti metodi di asserzione per verificare che vengano sollevate eccezioni.

assertRaises (eccezione, callable, * args, ** kwds)

Verifica che venga sollevata un'eccezione (primo argomento) quando una funzione viene chiamata con argomenti posizionali o parole chiave. Il test viene superato se viene sollevata l'eccezione prevista, è un errore se viene sollevata un'altra eccezione o non riesce se non viene sollevata alcuna eccezione. Per catturare uno qualsiasi di un gruppo di eccezioni, una tupla contenente le classi di eccezione può essere passata come eccezione.

Nell'esempio seguente, viene definita una funzione di test per verificare se ZeroDivisionError è sollevato.

import unittest

def div(a,b):
   return a/b
class raiseTest(unittest.TestCase):
   def testraise(self):
      self.assertRaises(ZeroDivisionError, div, 1,0)

if __name__ == '__main__':
   unittest.main()

La funzione testraise () utilizza la funzione assertRaises () per vedere se la divisione per zero si verifica quando viene chiamata la funzione div (). Il codice precedente solleverà un'eccezione. Ma cambia gli argomenti alla funzione div () come segue:

self.assertRaises(ZeroDivisionError, div, 1,1)

Quando un codice viene eseguito con queste modifiche, il test fallisce poiché ZeroDivisionError non si verifica.

F
================================================================
FAIL: testraise (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "raisetest.py", line 7, in testraise
      self.assertRaises(ZeroDivisionError, div, 1,1)
AssertionError: ZeroDivisionError not raised

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures = 1)

assertRaisesRegexp (eccezione, regexp, callable, * args, ** kwds)

Verifica che regexp corrisponda alla rappresentazione di stringa dell'eccezione sollevata. regexp può essere un oggetto espressione regolare o una stringa contenente un'espressione regolare adatta all'uso da parte di re.search ().

L'esempio seguente mostra come viene utilizzato assertRaisesRegexp ():

import unittest
import re

class raiseTest(unittest.TestCase):
   def testraiseRegex(self):
      self.assertRaisesRegexp(TypeError, "invalid", reg,"Point","TutorialsPoint")
      
if __name__ == '__main__':
   unittest.main()

Qui, testraseRegex () non fallisce come primo argomento. "Punto" si trova nella seconda stringa di argomenti.

================================================================
FAIL: testraiseRegex (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:/Python27/raiseTest.py", line 11, in testraiseRegex
      self.assertRaisesRegexp(TypeError, "invalid", reg,"Point","TutorialsPoint")
AssertionError: TypeError not raised
----------------------------------------------------------------------

Tuttavia, la modifica è come mostrato di seguito:

self.assertRaisesRegexp(TypeError, "invalid", reg,123,"TutorialsPoint")

Viene generata un'eccezione TypeError. Quindi, verrà visualizzato il seguente risultato:

================================================================
FAIL: testraiseRegex (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "raisetest.py", line 11, in testraiseRegex
      self.assertRaisesRegexp(TypeError, "invalid", reg,123,"TutorialsPoint")
AssertionError: "invalid" does not match 
   "first argument must be string or compiled pattern"
----------------------------------------------------------------------

Junit, il framework di test di unità Java (Pyunit è l'implementazione di JUnit) ha una comoda opzione di timeout. Se un test richiede più del tempo specificato, verrà contrassegnato come non riuscito.

Il framework di test di Python non contiene alcun supporto per il timeout. Tuttavia, un terzo modulo chiamato timeout-decorator può fare il lavoro.

Scarica e installa il modulo da -

https://pypi.python.org/packages/source/t/timeout-decorator/timeout-decorator-0.3.2.tar.gz

  • Importa timeout_decorator nel codice
  • Metti decoratore timeout prima del test
  • @timeout_decorator.timeout(10)

Se un metodo di test al di sotto di questa riga richiede più del timeout menzionato (10 minuti) qui, verrà sollevata un'eccezione TimeOutError. Ad esempio:

import time
import timeout_decorator

class timeoutTest(unittest.TestCase):

   @timeout_decorator.timeout(5)
   def testtimeout(self):
      print "Start"
   for i in range(1,10):
      time.sleep(1)
      print "%d seconds have passed" % i
      
if __name__ == '__main__':
   unittest.main()

unittest2 è un backport di funzionalità aggiuntive aggiunte al framework di test Python in Python 2.7 e successivi. È testato per funzionare su Python 2.6, 2.7 e 3. *. L'ultima versione può essere scaricata dahttps://pypi.python.org/pypi/unittest2

Per utilizzare unittest2 invece di unittest, è sufficiente sostituire import unittest con import unittest2.

Le classi in unittest2 derivano dalle classi appropriate in unittest, quindi dovrebbe essere possibile utilizzare l'infrastruttura in esecuzione di test unittest2 senza dover passare immediatamente tutti i test all'utilizzo di unittest2. Nel caso in cui intendi implementare nuove funzionalità, sottoclasse il tuo testcase daunittest2.TestCase invece di unittest.TestCase

Di seguito le novità di unittest2:

  • addCleanups per una migliore gestione delle risorse

  • Contiene molti nuovi metodi di asserzione

  • assertRaises come gestore di contesto, con accesso in seguito all'eccezione

  • Ha dispositivi a livello di modulo come setUpModule e tearDownModule

  • Include load_tests protocollo per caricare test da moduli o pacchetti

  • startTestRun e stopTestRun metodi su TestResult

In Python 2.7, invocate le funzionalità della riga di comando più unittime (incluso il test discover) con python -m unittest <args>.

Invece, unittest2 viene fornito con uno script unit2.

unit2 discover
unit2 -v test_module

Una gestione più efficiente di control-C durante un'esecuzione di test è fornita dall'opzione della riga di comando -c / - catch per unittest, insieme al catchbreakparametro. Con il comportamento di interruzione del blocco abilitato, control-C consentirà il completamento del test attualmente in esecuzione e l'esecuzione del test terminerà e riporterà tutti i risultati fino a quel momento. Un secondo control-c solleverà un KeyboardInterrupt nel solito modo.

Se viene chiamato il gestore unittest ma il gestore signal.SIGINT non è installato, allora chiama il gestore predefinito. Questo sarà normalmente il comportamento previsto dal codice che sostituisce un gestore installato e lo delega. Per i singoli test che richiedono una gestione unittest control-c disabilitata, è possibile utilizzare il decoratore removeHandler ().

Le seguenti funzioni di utilità abilitano la funzionalità di gestione control-c all'interno di framework di test:

unittest.installHandler ()

Installa il gestore control-c. Quando unsignal.SIGINT viene ricevuto tutti i risultati registrati hanno chiamato TestResult.stop ().

unittest.registerResult (risultato)

Registrati a TestResultoggetto per la manipolazione control-c. La registrazione di un risultato memorizza un riferimento debole ad esso, quindi non impedisce che il risultato venga raccolto dalla spazzatura.

unittest.removeResult (risultato)

Rimuovi un risultato registrato. Una volta che un risultato è stato rimosso, TestResult.stop () non verrà più chiamato su quell'oggetto risultato in risposta a un control-c.

unittest.removeHandler (function = None)

Quando viene chiamata senza argomenti, questa funzione rimuove il gestore control-c se è stato installato. Questa funzione può essere utilizzata anche come decoratore di test per rimuovere temporaneamente il gestore durante l'esecuzione del test.

GUI Test Runner

Il modulo unittest viene installato per scoprire ed eseguire i test in modo interattivo. Questa utility, uno script Python "inittestgui.py", utilizza il modulo Tkinter che è una porta Python per il kit di strumenti grafici TK. Fornisce una GUI facile da usare per la scoperta e l'esecuzione di test.

Python unittestgui.py

Fare clic sul pulsante "Scopri test". Viene visualizzata una piccola finestra di dialogo in cui è possibile selezionare la directory ei moduli da cui eseguire il test.

Infine, fai clic sul pulsante di avvio. I test verranno rilevati dal percorso selezionato e dai nomi dei moduli e il riquadro dei risultati visualizzerà i risultati.

Per vedere i dettagli del singolo test, selezionare e fare clic su test nella casella dei risultati -

Se non trovi questa utility nell'installazione di Python, puoi ottenerla dalla pagina del progetto http://pyunit.sourceforge.net/.

È disponibile anche un'utilità simile basata sul toolkit wxpython.

La distribuzione standard di Python contiene il modulo "Doctest". La funzionalità di questo modulo rende possibile la ricerca di parti di testo che sembrano sessioni interattive di Python ed esegue queste sessioni per vedere se funzionano esattamente come mostrato.

Doctest può essere molto utile nei seguenti scenari:

  • Per controllare che le docstring di un modulo siano aggiornate verificando che tutti gli esempi interattivi funzionino ancora come documentato.

  • Per eseguire test di regressione verificando che gli esempi interattivi da un file di test o da un oggetto di test funzionino come previsto.

  • Scrivere documentazione tutorial per un pacchetto, liberamente illustrata con esempi di input-output

In Python, una "docstring" è una stringa letterale che appare come la prima espressione in una classe, funzione o modulo. Viene ignorato quando viene eseguita la suite, ma viene riconosciuto dal compilatore e inserito nel file__doc__attributo della classe, funzione o modulo che lo racchiude. Poiché è disponibile tramite introspezione, è il luogo canonico per la documentazione dell'oggetto.

È una pratica abituale inserire un esempio di utilizzo di diverse parti del codice Python all'interno della docstring. Il modulo doctest permette di verificare che queste docstring siano aggiornate con le revisioni intermittenti nel codice.

Nel codice seguente, una funzione fattoriale è definita intervallata da un utilizzo di esempio. Per verificare se l'uso dell'esempio è corretto, chiama la funzione testmod () nel modulo doctest.

"""
This is the "example" module.

The example module supplies one function, factorial(). For example,

>>> factorial(5)
120
"""

def factorial(x):
   """Return the factorial of n, an exact integer >= 0.
   >>> factorial(-1)
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
   """
   
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testmod()

Immettere e salvare lo script precedente come FactDocTest.py e provare a eseguire questo script dalla riga di comando.

Python FactDocTest.py

Nessun output verrà mostrato a meno che l'esempio non fallisca. Ora, cambia la riga di comando come segue:

Python FactDocTest.py –v

La console ora mostrerà il seguente output:

C:\Python27>python FactDocTest.py -v
Trying:
   factorial(5)
Expecting:
   120
ok
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
2 items passed all tests:
   1 tests in __main__
   1 tests in __main__.factorial
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

Se, d'altra parte, il codice della funzione factorial () non fornisce il risultato atteso in docstring, verrà visualizzato il risultato del fallimento. Ad esempio, cambia f = 2 al posto di f = 1 nello script sopra ed esegui di nuovo il doctest. Il risultato sarà il seguente:

Trying:
   factorial(5)
Expecting:
   120
**********************************************************************
File "docfacttest.py", line 6, in __main__
Failed example:
factorial(5)
Expected:
   120
Got:
   240
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
1 items passed all tests:
   1 tests in __main__.factorial
**********************************************************************
1 items had failures:
   1 of 1 in __main__
2 tests in 2 items.
1 passed and 1 failed.
***Test Failed*** 1 failures.

Doctest: controllo degli esempi in un file di testo

Un'altra semplice applicazione di doctest è testare esempi interattivi in ​​un file di testo. Questo può essere fatto con la funzione testfile ().

Il testo seguente è memorizzato in un file di testo denominato "esempio.txt".

Using ''factorial''
-------------------
This is an example text file in reStructuredText format. First import
''factorial'' from the ''example'' module:
   >>> from example import factorial
Now use it:
   >>> factorial(5)
   120

Il contenuto del file viene trattato come docstring. Per verificare gli esempi nel file di testo, utilizzare la funzione testfile () del modulo doctest.

def factorial(x):
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testfile("example.txt")
  • Come con testmod (), testfile () non mostrerà nulla a meno che un esempio non fallisca. Se un esempio non riesce, gli esempi e le cause degli errori vengono stampati sulla console, utilizzando lo stesso formato di testmod ().

  • Nella maggior parte dei casi un copia e incolla di una sessione di console interattiva funziona bene, ma doctest non sta cercando di eseguire un'esatta emulazione di una specifica shell Python.

  • Qualsiasi output atteso deve seguire immediatamente la riga finale ">>>" o "..." contenente il codice e l'output previsto (se presente) si estende alla riga successiva ">>>" o di tutti gli spazi.

  • L'output atteso non può contenere una riga di tutti gli spazi, poiché tale riga viene presa per segnalare la fine dell'output atteso. Se l'output previsto contiene una riga vuota, inserisci <BLANKLINE> nel tuo esempio di doctest ogni posizione è prevista una riga vuota.

L'API doctest ruota attorno alle seguenti due classi container utilizzate per memorizzare esempi interattivi da docstrings:

  • Example - Una singola istruzione Python, abbinata al suo output previsto.

  • DocTest - Una raccolta di esempi, tipicamente estratti da una singola docstring o da un file di testo.

Le seguenti classi di elaborazione aggiuntive sono definite per trovare, analizzare ed eseguire e controllare esempi di doctest:

  • DocTestFinder - Trova tutte le docstring in un dato modulo e utilizza un DocTestParser per creare un DocTest da ogni docstring che contiene esempi interattivi.

  • DocTestParser - Crea un oggetto doctest da una stringa (come la docstring di un oggetto).

  • DocTestRunner - Esegue gli esempi in un doctest e utilizza un OutputChecker per verificarne l'output.

  • OutputChecker - Confronta l'output effettivo di un esempio doctest con l'output previsto e decide se corrispondono.

Classe DocTestFinder

È una classe di elaborazione usata per estrarre i doctest rilevanti per un dato oggetto, dalla sua docstring e dalle docstring dei suoi oggetti contenuti. Doctests può attualmente essere estratto dai seguenti tipi di oggetti: moduli, funzioni, classi, metodi, metodi statici, metodi di classe e proprietà.

Questa classe definisce il metodo find (). Restituisce un elenco dei DocTest definiti dalla docstring dell'oggetto o da una qualsiasi delle docstring degli oggetti contenuti.

DocTestParser Class

È una classe di elaborazione utilizzata per estrarre esempi interattivi da una stringa e utilizzarli per creare un oggetto DocTest. Questa classe definisce i seguenti metodi:

  • get_doctest() - Estrai tutti gli esempi di doctest dalla stringa data e raccoglili in un file DocTest oggetto.

  • get_examples(string[, name]) - Estrae tutti gli esempi di doctest dalla stringa data e li restituisce come un elenco di file Exampleoggetti. I numeri di riga sono basati su 0. Il nome dell'argomento facoltativo è un nome che identifica questa stringa e viene utilizzato solo per i messaggi di errore.

  • parse(string[, name]) - Dividi la stringa data in esempi e testo intermedio e restituiscili come un elenco di alternanze Examplese archi. Numeri di riga perExamplessono a base 0. Il nome dell'argomento facoltativo è un nome che identifica questa stringa e viene utilizzato solo per i messaggi di errore.

DocTestRunner Class

Questa è una classe di elaborazione utilizzata per eseguire e verificare gli esempi interattivi in ​​un DocTest. I seguenti metodi sono definiti in esso:

report_start ()

Segnala che il test runner sta per elaborare l'esempio fornito. Questo metodo viene fornito per consentire le sottoclassi diDocTestRunnerpersonalizzarne l'output; non dovrebbe essere chiamato direttamente

report_success ()

Segnala che l'esempio fornito è stato eseguito correttamente. Questo metodo viene fornito per consentire alle sottoclassi di DocTestRunner di personalizzare il proprio output; non dovrebbe essere chiamato direttamente.

report_failure ()

Segnala che l'esempio fornito non è riuscito. Questo metodo viene fornito per consentire le sottoclassi diDocTestRunnerpersonalizzarne l'output; non dovrebbe essere chiamato direttamente.

report_unexpected_exception ()

Segnala che l'esempio fornito ha sollevato un'eccezione imprevista. Questo metodo viene fornito per consentire alle sottoclassi di DocTestRunner di personalizzare il proprio output; non dovrebbe essere chiamato direttamente.

eseguire (test)

Eseguire gli esempi in test (un oggetto DocTest) e visualizzare i risultati utilizzando la funzione writer out .

riassumere ([verbose])

Stampa un riepilogo di tutti i casi di test che sono stati eseguiti da questo DocTestRunner e restituisci una tupla TestResults con nome (fallito, tentato). L' argomento dettagliato facoltativo controlla il livello di dettaglio del riepilogo. Se la verbosità non è specificata, viene utilizzata la verbosità del DocTestRunner.

Classe OutputChecker

Questa classe viene utilizzata per verificare se l'output effettivo di un esempio di doctest corrisponde all'output previsto.

I seguenti metodi sono definiti in questa classe:

check_output ()

Ritorno Truese l'output effettivo di un esempio ( got ) corrisponde all'output atteso ( want ). Queste stringhe sono sempre considerate corrispondenti se sono identiche; ma a seconda dell'opzione che sta utilizzando il test runner, sono possibili anche diversi tipi di corrispondenza non esatta. Vedere la sezione Flag di opzione e direttive per ulteriori informazioni sui flag di opzione.

output_difference ()

Restituisce una stringa che descrive le differenze tra l'output previsto per un dato esempio ( esempio ) e l'output effettivo ( got ).

Integrazione di DocTest con Unittest

Il modulo doctest fornisce due funzioni che possono essere utilizzate per creare suite di test unittest da moduli e file di testo contenenti doctest. Per l'integrazione con unittest test discovery, includi una funzione load_tests () nel tuo modulo di test -

import unittest
import doctest
import doctestexample

def load_tests(loader, tests, ignore):
   tests.addTests(doctest.DocTestSuite(doctestexample))
   return tests

Verrà formato un TestSuite combinato di test da unittest e doctest e ora può essere eseguito dal metodo main () del modulo unittest o dal metodo run ().

Le seguenti sono le due funzioni principali per la creazione unittest.TestSuite istanze da file di testo e moduli con i doctests -

doctest.DocFileSuite ()

Viene utilizzato per convertire i test doctest da uno o più file di testo in un file unittest.TestSuite. Unittest.TestSuite restituito deve essere eseguito dal framework unittest ed esegue gli esempi interattivi in ​​ogni file. Se uno qualsiasi degli esempi in un file fallisce, lo unit test sintetizzato fallisce e afailureException viene sollevata un'eccezione che mostra il nome del file contenente il test e un numero di riga (a volte approssimativo).

doctest.DocTestSuite ()

Viene utilizzato per convertire i test doctest per un modulo in un file unittest.TestSuite.

Unittest.TestSuite restituito deve essere eseguito dal framework unittest ed esegue ogni doctest nel modulo. Se uno qualsiasi dei doctest fallisce, lo unit test sintetizzato fallisce e afailureException viene sollevata un'eccezione che mostra il nome del file contenente il test e un numero di riga (a volte approssimativo)

Sotto le coperte, DocTestSuite () crea un file unittest.TestSuite di istanze doctest.DocTestCase e DocTestCase è una sottoclasse di unittest.TestCase.

Allo stesso modo, DocFileSuite () crea un unittest.TestSuite dalle istanze di doctest.DocFileCase e DocFileCase è una sottoclasse di DocTestCase.

Quindi entrambi i modi per creare un unittest.TestSuite eseguono istanze di DocTestCase. Quando esegui tu stesso le funzioni doctest, puoi controllare le opzioni doctest in uso direttamente, passando flag di opzione alle funzioni doctest.

Tuttavia, se stai scrivendo un framework unittest, unittest alla fine controlla quando e come vengono eseguiti i test. L'autore del framework in genere vuole controllare le opzioni di reporting di doctest (forse, ad esempio, specificato dalle opzioni della riga di comando), ma non c'è modo di passare le opzioni da unittest a doctest test runner.

Fu nel 2004 che Holger Krekel ribattezzò il suo stdpacchetto, il cui nome veniva spesso confuso con quello della libreria standard fornita con Python, al nome (solo leggermente meno confuso) "py". Sebbene il pacchetto contenga diversi sotto-pacchetti, ora è noto quasi interamente per il suo framework py.test.

Il framework py.test ha creato un nuovo standard per i test di Python ed è diventato molto popolare tra molti sviluppatori oggi. Gli idiomi eleganti e pitonici introdotti per la scrittura di prova hanno reso possibile scrivere suite di test in uno stile molto più compatto.

py.test è un'alternativa no-boilerplate al modulo unittest standard di Python. Nonostante sia uno strumento di test completo ed estensibile, vanta una sintassi semplice. Creare una suite di test è facile come scrivere un modulo con un paio di funzioni.

py.test funziona su tutti i sistemi operativi POSIX e WINDOWS (XP / 7/8) con Python versione 2.6 e successive.

Installazione

Utilizzare il codice seguente per caricare il modulo pytest nella distribuzione Python corrente e un'utilità py.test.exe. I test possono essere eseguiti utilizzando entrambi.

pip install pytest

Utilizzo

Puoi semplicemente usare l'istruzione assert per affermare le aspettative del test. l'introspezione assert di pytest riporterà in modo intelligente i valori intermedi dell'espressione assert liberandoti dalla necessità di imparare i molti nomi diJUnit legacy methods.

# content of test_sample.py
def func(x):
   return x + 1
   
def test_answer():
   assert func(3) == 5

Utilizzare la seguente riga di comando per eseguire il test precedente. Una volta eseguito il test, sulla console viene visualizzato il seguente risultato:

C:\Python27>scripts\py.test -v test_sample.py
============================= test session starts =====================
platform win32 -- Python 2.7.9, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- C:\Pyth
on27\python.exe
cachedir: .cache
rootdir: C:\Python27, inifile:
collected 1 items
test_sample.py::test_answer FAILED
================================== FAILURES =====================
_________________________________ test_answer _________________________________
   def test_answer():
>  assert func(3) == 5
E     assert 4 == 5
E     + where 4 = func(3)
test_sample.py:7: AssertionError
========================== 1 failed in 0.05 seconds ====================

Il test può anche essere eseguito dalla riga di comando includendo il modulo pytest utilizzando l'opzione –m.

python -m pytest test_sample.py

Raggruppamento di più test in una classe

Una volta che inizi ad avere più di pochi test, spesso ha senso raggruppare i test in modo logico, in classi e moduli. Scriviamo una classe contenente due test:

class TestClass:
   def test_one(self):
      x = "this"
      assert 'h' in x
   def test_two(self):
      x = "hello"
      assert hasattr(x, 'check')

Verrà visualizzato il seguente risultato del test:

C:\Python27>scripts\py.test -v test_class.py
============================= test session starts =====================
platform win32 -- Python 2.7.9, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- C:\Pyt
on27\python.exe
cachedir: .cache
rootdir: C:\Python27, inifile:
collected 2 items
test_class.py::TestClass::test_one PASSED
test_class.py::TestClass::test_two FAILED
================================== FAILURES =====================
_____________________________ TestClass.test_two ______________________________
self = <test_class.TestClass instance at 0x01309DA0>

   def test_two(self):
      x = "hello"
>  assert hasattr(x, 'check')
E     assert hasattr('hello', 'check')

test_class.py:7: AssertionError
===================== 1 failed, 1 passed in 0.06 seconds ======================

Il progetto del naso è stato rilasciato nel 2005, l'anno successivo py.testha ricevuto la sua veste moderna. È stato scritto da Jason Pellerin per supportare gli stessi idiomi di test che erano stati sperimentati da py.test, ma in un pacchetto che è più facile da installare e mantenere.

Il nose il modulo può essere installato con l'aiuto di pip utility

pip install nose

Questo installerà il modulo nose nell'attuale distribuzione di Python così come un nosetest.exe, il che significa che il test può essere eseguito usando questa utility oltre che usando l'opzione –m.

C:\python>nosetests –v test_sample.py
Or
C:\python>python –m nose test_sample.py

nose raccoglie test da unittest.TestCasesottoclassi, ovviamente. Possiamo anche scrivere semplici funzioni di test, così come classi di test che non sono sottoclassi di unittest.TestCase. nose fornisce anche una serie di funzioni utili per scrivere test a tempo, testare le eccezioni e altri casi d'uso comuni.

noseraccoglie i test automaticamente. Non è necessario raccogliere manualmente i casi di test nelle suite di test. L'esecuzione dei test è reattiva, da alloranose inizia l'esecuzione dei test non appena viene caricato il primo modulo di test.

Come con il modulo unittest, nose supporta i dispositivi a livello di pacchetto, modulo, classe e test case, quindi l'inizializzazione costosa può essere eseguita il meno frequentemente possibile.

Utilizzo di base

Consideriamo nosetest.py simile allo script usato in precedenza -

# content of nosetest.py
def func(x):
   return x + 1
   
def test_answer():
   assert func(3) == 5

Per eseguire il test precedente, utilizzare la seguente sintassi della riga di comando:

C:\python>nosetests –v nosetest.py

L'output visualizzato sulla console sarà il seguente:

nosetest.test_answer ... FAIL
================================================================
FAIL: nosetest.test_answer
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python34\lib\site-packages\nose\case.py", line 198, in runTest
      self.test(*self.arg)
   File "C:\Python34\nosetest.py", line 6, in test_answer
      assert func(3) == 5
AssertionError
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures = 1)

nose può essere integrato con DocTest utilizzando with-doctest opzione nella riga di comando bove.

\nosetests --with-doctest -v nosetest.py

Puoi usare nose in uno script di test -

import nose
nose.main()

Se non desideri che lo script di test esca con 0 in caso di successo e 1 in caso di fallimento (come unittest.main), usa invece nose.run () -

import nose
result = nose.run()

Il risultato sarà vero se l'esecuzione del test ha esito positivo, o falso se fallisce o solleva un'eccezione non rilevata.

nosesupporta i dispositivi (metodi di installazione e smontaggio) a livello di pacchetto, modulo, classe e test. Come per i dispositivi py.test o unittest, l'installazione viene sempre eseguita prima di qualsiasi test (o raccolta di test per pacchetti e moduli di test); lo smontaggio viene eseguito se la configurazione è stata completata con successo, indipendentemente dallo stato della corsa di prova.

Il modulo nose.tools fornisce una serie di aiuti per i test che potresti trovare utili, inclusi i decoratori per limitare il tempo di esecuzione del test e il test per le eccezioni, e tutti gli stessi metodi assertX trovati in unittest.TestCase.

  • nose.tools.ok_(expr, msg = None) - Abbreviazione di assert.

  • nose.tools.eq_(a, b, msg = None) - Abbreviazione di "assert a == b,"% r! =% R "% (a, b)

  • nose.tools.make_decorator(func) - Avvolge un decoratore di prova in modo da replicare correttamente i metadati della funzione decorata, comprese le cose aggiuntive del naso (vale a dire, installazione e smontaggio).

  • nose.tools.raises(*exceptions) - Il test deve sollevare una delle eccezioni previste per essere superato.

  • nose.tools.timed(limit) - Il test deve terminare entro il limite di tempo specificato per essere superato

  • nose.tools.istest(func) - Decoratore per contrassegnare una funzione o un metodo come prova

  • nose.tools.nottest(func) - Decoratore per contrassegnare una funzione o un metodo come non un test

Test parametrizzati

Il framework di test di Python, unittest, non ha un modo semplice per eseguire casi di test parametrizzati. In altre parole, non puoi passare facilmente argomenti in un fileunittest.TestCase da fuori.

Tuttavia, le porte del modulo pytest testano la parametrizzazione in diversi modi ben integrati:

  • pytest.fixture() consente di definire la parametrizzazione a livello di funzioni del faro.

  • @pytest.mark.parametrizepermette di definire la parametrizzazione a livello di funzione o classe. Fornisce più set di argomenti / dispositivi per una particolare funzione o classe di test.

  • pytest_generate_tests consente di implementare il proprio schema o estensioni di parametrizzazione dinamica personalizzati.

Un modulo di terze parti "nose-parametrizzato" consente il test parametrizzato con qualsiasi framework di test Python. Può essere scaricato da questo link -https://github.com/wolever/nose-parameterized