Python Mock Prozess für Unit Testing

8

Hintergrund:
Ich schreibe gerade ein Prozessüberwachungstool (Windows und Linux) in Python und implementiere Unit-Testabdeckung. Der Prozessmonitor verbindet sich mit der Windows-API-Funktion EnumProcesses unter Windows und überwacht das Verzeichnis / proc auf Linux, um aktuelle Prozesse zu finden. Die Prozessnamen und Prozess-IDs werden dann in ein Protokoll geschrieben, auf das die Komponententests zugreifen können.

Frage:
Wenn ich das Überwachungsverhalten Unit-Unit-Test, brauche ich einen Prozess zu starten und zu beenden. Ich würde mich freuen, wenn es einen (plattformübergreifenden?) Weg geben würde, einen gefälschten Systemprozess zu starten und zu beenden, den ich eindeutig benennen (und dessen Erstellung in einem Komponententest nachverfolgen könnte).

Erste Ideen:

  • Ich könnte subprocess.Popen () verwenden, um einen beliebigen Systemprozess zu öffnen läuft auf einige Probleme. Die Komponententests könnten fälschlicherweise bestanden werden, wenn der Prozess, den ich zum Testen verwende, ebenfalls vom System ausgeführt wird. Außerdem werden die Komponententests über die Befehlszeile ausgeführt, und jeder Linux-Prozess, an den ich denken kann, unterbricht das Terminal (nano usw.).
  • Ich könnte einen Prozess starten und ihn anhand seiner Prozess-ID verfolgen, aber ich bin mir nicht sicher, wie ich das tun soll, ohne das Terminal anzuhalten.

Dies sind nur Gedanken und Beobachtungen aus den ersten Tests und ich würde es lieben, wenn jemand mich in einem dieser Punkte falsch beweisen könnte.

Ich benutze Python 2.6.6.

Bearbeiten:
Erhalten Sie alle Linux-Prozess-IDs:

%Vor%

Alle Windows-Prozess-IDs abrufen:

%Vor%

Windows-Code ist von hier

    
alexquinn 26.02.2013, 15:47
quelle

2 Antworten

5

edit: Diese Antwort wird lang :), aber einige meiner ursprünglichen Antworten gelten immer noch, also lasse ich sie:)

Dein Code unterscheidet sich nicht sehr von meiner ursprünglichen Antwort. Einige meiner Ideen gelten noch.

Wenn Sie Komponententest schreiben, möchten Sie nur Ihre Logik testen. Wenn Sie Code verwenden, der mit dem Betriebssystem interagiert, möchten Sie diesen Teil normalerweise nachahmen. Der Grund dafür ist, dass Sie nicht viel Kontrolle über die Ausgabe dieser Bibliotheken haben, wie Sie herausgefunden haben. So ist es einfacher, diese Anrufe zu verspotten.

In diesem Fall gibt es zwei Bibliotheken, die mit dem System interagieren: os.listdir und EnumProcesses . Da du sie nicht geschrieben hast, können wir sie leicht fälschen, um das zurückzugeben, was wir brauchen. Was in diesem Fall eine Liste ist.

Aber warte, in deinem Kommentar hast du erwähnt:

  

"Das Problem, das ich damit habe, ist jedoch, dass es wirklich nicht testet   dass mein Code neue Prozesse auf dem System sieht, aber dass der   Code überwacht neue Elemente in einer Liste korrekt. "

Die Sache ist, dass wir nicht brauchen, um den Code zu testen, der tatsächlich die Prozesse auf dem System überwacht , weil es ein Code von Drittanbietern ist. Was wir testen müssen, ist, dass Ihre Codelogik die zurückgegebenen Prozesse verarbeitet . Denn das ist der Code, den du geschrieben hast. Der Grund, warum wir über eine Liste testen, liegt darin, dass Ihre Logik dies tut. os.listir und EniumProcesses geben eine Liste von pids (numerische Strings bzw. Integer) zurück und Ihr Code agiert in dieser Liste.

Ich gehe davon aus, dass sich Ihr Code in einer Klasse befindet (Sie verwenden self in Ihrem Code). Ich gehe auch davon aus, dass sie innerhalb ihrer eigenen Methoden isoliert sind (Sie verwenden return ). Das wird also etwas sein, was ich ursprünglich vorgeschlagen habe, außer mit tatsächlichem Code :) Idk, wenn sie in der gleichen Klasse oder in verschiedenen Klassen sind, aber es spielt keine Rolle.

Linux-Methode

Nun ist das Testen Ihrer Linux-Prozessfunktion nicht so schwierig. Sie können os.listdir patchen, um eine Liste von PIDs zurückzugeben.

%Vor%

Nun zum Test.

%Vor%

Windows-Methode

Das Testen der Methode Ihres Windows ist etwas komplizierter. Was ich tun würde, ist folgendes:

%Vor%

Ich habe den Code in zwei Methoden getrennt, um das Lesen zu erleichtern (ich glaube, Sie tun das bereits). Hier ist der knifflige Teil, EnumProcesses benutzt Zeiger und sie sind nicht einfach zu spielen. Eine andere Sache ist, dass ich nicht weiß, wie man mit Zeigern in Python arbeitet, also konnte ich dir nicht von einem einfachen Weg erzählen, das herauszuspielen = P

Was ich Ihnen sagen kann, ist, es einfach nicht zu testen. Deine Logik dort ist sehr minimal. Neben dem Erhöhen der Größe von count erstellt alles andere in dieser Funktion das Leerzeichen, das EnumProcesses Zeiger verwenden. Vielleicht können Sie der Zählgröße ein Limit hinzufügen, aber ansonsten ist diese Methode kurz und bündig. Es gibt die Windows-Prozesse und nichts mehr zurück. Genau das, was ich in meinem ursprünglichen Kommentar gefragt habe:)

Also lassen Sie diese Methode in Ruhe. Teste es nicht. Stellen Sie jedoch sicher, dass alles, das getWindowsProcess und getLinuxProcess verwendet, laut meinem ursprünglichen Vorschlag ausgehöhlt wird.

Hoffentlich macht das mehr Sinn :) Wenn es mich nicht informiert und vielleicht können wir eine Chat-Sitzung haben oder einen Videoanruf oder etwas machen.

ursprüngliche Antwort

Ich bin nicht genau sicher, wie ich das mache, was Sie fragen, aber wann immer ich Code testen muss, der von äußeren Kräften abhängt (externe Bibliotheken, Popen oder in diesem Fall Prozesse), mache ich diese Teile aus.

Nun, ich weiß nicht, wie Ihr Code strukturiert ist, aber vielleicht können Sie so etwas tun:

%Vor%

Diese beiden Methoden tun nur eins , erhalten die Liste der Prozesse. Für Windows könnte es nur ein Aufruf dieser API sein und für Linux nur das / proc dir. Das ist alles, nichts mehr. Die Logik für die Handhabung der Prozesse wird woanders hingehen. Dies macht es extrem einfach, diese Methoden auszuspielen, da ihre Implementierungen nur API-Aufrufe sind, die eine Liste zurückgeben.

Ihr Code kann sie dann einfach aufrufen:

%Vor%

In Ihrem Test können Sie dann eine spöttische Bibliothek wie Fudge verwenden. Sie verspotten diese beiden Methoden, um das zurückzugeben, was Sie erwarten .

Auf diese Weise testen Sie Ihre Logik, da Sie steuern können, was das Ergebnis sein wird.

%Vor%

Wenn Sie Ihren Code auf diese Weise testen, erhalten Sie keine 100% ige Codeabdeckung (da Ihre verspotteten Methoden nicht ausgeführt werden), aber das ist in Ordnung. Sie testen Ihren Code und nicht die von Drittanbietern, was zählt.

Hoffentlich kann Ihnen das helfen. Ich weiß, dass es deine Frage nicht beantwortet, aber vielleicht kannst du damit herausfinden, wie du deinen Code am besten testen kannst.

    
Carlos V 26.02.2013, 21:36
quelle
0

Deine ursprüngliche Idee, Subprozesse zu verwenden, ist eine gute Idee. Erstellen Sie einfach Ihre eigene ausführbare Datei und benennen Sie sie als etwas, das sie als Testobjekt identifiziert. Vielleicht mache es so etwas wie Schlaf für eine Weile.

Alternativ könnten Sie das Multiprocessing-Modul tatsächlich verwenden. Ich habe Python nicht viel in Windows verwendet, aber Sie sollten in der Lage sein, prozessidentifizierende Daten aus dem von Ihnen erstellten Process-Objekt zu erhalten:

%Vor%     
underrun 18.03.2014 14:45
quelle