2017-08-09 3 views
0

J'ai un script qui utilise subprocess.check_output d'une commande. Il existe des cas où cette commande peut échouer et déclencher un subprocess.CalledProcessError.Comment tester un sous-processus.CalledProcessError

Je tente d'écrire un test unitaire (en utilisant pytest pour exécuter le test) pour cette fonction et de tester la condition d'exception.

pytest 3.1.2
Python 3.5.3

j'ai écrit ce petit bout de code à explorer avec en vain.

# mytest.py 
import subprocess 

def test_sub(): 
    try: 
     command_output = subprocess.check_output("unzip x".split()) 
     # unzip x is used to raise the exception when running with python 
     # but would be replaced by proper command that may fail 
     output = command_output 
    except subprocess.CalledProcessError as cpe: 
    #except Exception as cpe: 
     print("\nType of error:", type(cpe)) 
     print(cpe.args) 
     output = "unzip" 
    return output 

if __name__ == '__main__': 
    print(test_sub()) 

Lorsqu'il est exécuté avec python mytest.py la sortie est unzip comme prévu depuis la commande unzip échouera et augmenter l'erreur.

C'est le code pour tester la fonction

# test.py 
import unittest 
import unittest.mock as mock 
from mytest import test_sub 
import subprocess 

class SubErrorTest(unittest.TestCase): 

    @mock.patch('mytest.subprocess', autospec=True) 
    def test_subprocess_error_thrown(self, mock_subprocess): 

     mock_subprocess.check_output.side_effect = subprocess.CalledProcessError(returncode=2,cmd=["bad"]) 
     output = test_sub() 
     self.assertEqual("unzip", output) 

Effectué pytest test.py le test échoue avec l'erreur

output = test_sub() #error thrown from here in test 

test.py:

def test_sub(): 
    try: 
     command_output = subprocess.check_output("unzip x".split()) 
     output = command_output 
except subprocess.CalledProcessError as cpe: #error is indicated here 

E TypeError: catching classes that do not inherit from BaseException is not allowed

Si je commente except subprocess.CalledProcessError as cpe: et uncomment #except Exception as cpe: le test passe avec le ouptut:

test.py
Type of error: <class 'subprocess.CalledProcessError'>
()

Cela semble suggérer Gérer à moi que l'erreur est lancée comme spécifié dans le simulacre et attrapé et le bloc d'exception est exécuté. La question est alors, pourquoi ne fonctionne-t-il pas en attrapant subprocess.CalledProcessError.

Ce retour True

isinstance(subprocess.CalledProcessError(returncode=2,cmd=["bad"]), BaseException) 

À ce stade, je suppose qu'il ya quelque chose qui me manque dans le processus.

Qu'est-ce qui me manque?

Répondre

1

Je pense que vous corrigez le mauvais chemin.

@mock.patch('mytest.subprocess', autospec=True) 

Le chemin doit être le chemin vers le module testé et non le test lui-même. Ce que je pense qui se passe est votre sous-processus moqueur dans l'espace de noms test.py si vous définissez l'effet side_effect à subprocess.CalledProcessError vous le définissez à un simulacre. Vous pouvez le vérifier en consignant l'effet side_effect après l'avoir défini.