Pisanie testów jednostkowych dla klasy, która uruchamia zewnętrzny EXE

9

Napisałem klasę C #, która służy do uruchamiania listy plików EXE (nie jednego z plików EXE innych firm, które muszę uruchomić) i utrzymywania ich w działaniu (od czasu do czasu sprawdzę, czy nadal działa, i uruchomię je, jeśli nie) .

Jestem w stanie przetestować podstawową logikę dodawania, usuwania itp. Jak przeprowadzić test jednostkowy, że faktyczna praca polegająca na przechowywaniu plików EXE będzie działać?

Moją początkową myślą jest uruchomienie fałszywego pliku EXE, który zamyka się po 1 sekundzie, a następnie użyć go do przetestowania. Czy to nie jest dziedzina testów jednostkowych?

MattW
źródło

Odpowiedzi:

12

Moją początkową myślą jest uruchomienie fałszywego pliku EXE, który zamyka się po 1 sekundzie, a następnie użyć go do przetestowania. Czy to nie jest dziedzina testów jednostkowych?

Czy to dobry test? Jasne, więc stwórz to. Czy jest to „test jednostkowy” w prawdziwym tego słowa znaczeniu? Nie sądzę, nazwałbym to „testem systemu” lub czymś takim, ale to nie czyni testu mniej wartościowym.

Doktor Brown
źródło
9

Wyśmiewaj się na wyższym poziomie. Utwórz wokół siebie klasę proxy Process.Start(), podrób to w teście i sprawdź dane wejściowe.

public interface IProcessProxy
{
     ProcessInfo Start(string application, string[] arguments);
}

public class ProcessProxy : IProcessProxy
{
    public ProcessInfo Start(string application, string[] arguments)
    {
        return Process.Start(application, arguments);
    }
}

// You could use a mocking framework for this, but for the purposes
// of this example ...
public class FakeProcessProxy : IProcessProxy
{
    private string _expectedApplication;
    private string[] _expectedArguments;
    private ProcessInfo response;

    public FakeProxy(string expectedApplication, string[] expectedArguments, ProcessInfo response)
    {
         _expectedApplication = expectedApplication;
         _expectedArguments = expectedArguments;
    }

    public ProcessInfo Start(string application, string[] arguments)
    {
         // compare input to expectations and throw exception if not matching
         return _response;
    }
}

// You can also use an IoC framework to inject your IProcessProxy, but I won't.
public class ClassUnderTest
{
    public ClassUnderTest(IProcessProxy proxy)
    {
        _proxy = proxy;
    }

    public ClassUnderTest() : this(new ProcessProxy())
    {
    }

    public void MethodUnderTest()
    {
        // Do stuff

        ProcessInfo process = _proxy.Start(@"C:\Program Files\App\App.exe", new[] { "arg1", "arg2" });
        process.WaitForExit();

        if (process.ExitCode == 0)
        {
            // Act on success
        }
        else
        {
            // Act on failure
        }
    }   
}

Wszędzie tam, gdzie musisz wykorzystać ClassUnderTest w kodzie aplikacji, użyj domyślnego konstruktora. W testach przekaż FakeProcessProxy drugiemu konstruktorowi, używając oczekiwanych parametrów uruchomienia proxy i wyniku testu w konstruktorze fałszywego.

pdr
źródło
4

Jeśli ściśle przestrzegasz filozofii unittesting (nacisk na jednostkę ), nie powinieneś tworzyć pliku exe, ale zamiast tego sprawdzić, czy twoja klasa wywołuje interfejsy do odradzania i monitorowania tego procesu poprawnie. W końcu chcesz przetestować swoją klasę, a nie bibliotekę odpowiedzialną za obsługę procesów.

Ale z pragmatycznego punktu widzenia twoje podejście jest w porządku, choć 1 sekunda wydaje się trochę długa.

keppla
źródło
1

Zrobiłem coś podobnego, ale właśnie zadzwoniłem ping localhost. Oszczędza kłopotów związanych z umieszczaniem plików wykonywalnych na serwerze kompilacji

Ben
źródło