Wie können Eingaben von stdin, Dateien und Umgebungsvariablen an Python-Unit-Tests übergeben werden?




unit-testing user-input (3)

So schreiben Sie Tests, bei denen Bedingungen wie die folgenden auftreten:

  1. Benutzereingabe testen
  2. Testeingabe aus einer Datei gelesen.
  3. Testeingabe von einer Umgebungsvariablen gelesen.

Es wäre toll, wenn mir jemand zeigen könnte, wie ich mich den oben genannten Szenarien annähern kann; Es wäre immer noch toll, wenn du mich auf ein paar Dokumente / Artikel / Blogposts verweisen könntest, die ich lesen könnte.


In allen drei Situationen, die Sie beschrieben haben, müssen Sie speziell darauf achten, dass Sie lockere Verbindungen in Ihrem Design verwenden.

Müssen Sie Pythons raw_input Methode wirklich testen? Die open Methode? os.environ.get ? Nein.

Sie müssen Ihr Design so einrichten, dass Sie andere Möglichkeiten zum Abrufen dieser Eingabe verwenden können. Dann werfen Sie während Ihrer raw_input einen Stub irgendeiner Art, der raw_input nicht raw_input oder nicht open .

Zum Beispiel könnte Ihr normaler Code etwas wie sein:

import os
def say_hello(input_func):
    name = input_func()
    return "Hello " + name

def prompt_for_name():
    return raw_input("What is your name? ")

print say_hello(prompt_for_name)
# Normally would pass in methods, but lambdas can be used for brevity
print say_hello(lambda: open("a.txt").readline())
print say_hello(lambda: os.environ.get("USER"))

Die Sitzung sieht folgendermaßen aus:

What is your name? somebody
Hello somebody
Hello [some text]

Hello mark

Dann wird dein Test wie folgt aussehen:

def test_say_hello():
    output = say_hello(lambda: "test")
    assert(output == "Hello test")

Denken Sie daran, dass Sie die IO-Funktionen einer Sprache nicht testen sollten (es sei denn, Sie sind derjenige, der die Sprache gestaltet, was eine völlig andere Situation ist).


Wenn Sie mit raw_input (oder einer anderen spezifischen Eingabequelle) verbunden sind, bin ich ein großer Befürworter der Mock-Bibliothek . Angesichts des Codes, den Mark Ruschakoff in seinem Beispiel verwendete:

def say_hello():
    name = raw_input("What is your name? ")
    return "Hello " + name

Ihr Testcode könnte mock verwenden:

import mock

def test_say_hello():
     with mock.patch('__builtin__.raw_input', return_value='dbw'):
         assert say_hello() == 'Hello dbw'

     with mock.patch('__builtin__.raw_input', side_effect=['dbw', 'uki']):
         assert say_hello() == 'Hello dbw'
         assert say_hello() == 'Hello uki'

Diese Behauptungen würden bestehen. Beachten Sie, dass side_effect die Elemente der Liste in der richtigen Reihenfolge zurückgibt. Es kann so viel mehr! Ich würde empfehlen, die Dokumentation zu überprüfen.


Pyty verwenden :

import os


def test_user_input(monkeypatch):
    inputs = [10, 'y']
    input_generator = (i for i in inputs)
    monkeypatch.setattr('__builtin__.raw_input', lambda prompt: next(input_generator))
    assert raw_input('how many?') == 10
    assert raw_input('you sure?') == 'y'


def test_file_input(tmpdir):
    fixture = tmpdir.join('fixture.txt')
    fixture.write(os.linesep.join(['1', '2', '3']))
    fixture_path = str(fixture.realpath())
    with open(fixture_path) as f:
        assert f.readline() == '1' + os.linesep


def test_environment_input(monkeypatch):
    monkeypatch.setenv('STAGING', 1)
    assert os.environ['STAGING'] == '1'






user-input