Gravando testes de unidade para uma classe que inicia EXE externo

9

Eu escrevi uma classe C # que é usada para iniciar uma lista de EXEs (não é uma das minhas - EXEs de terceiros que eu tenho que executar) e mantê-los em execução (verificarei ocasionalmente para garantir que ele ainda esteja em execução e, se não for,) .

Eu sou capaz de testar a lógica básica de adicionar, remover, etc. Como faço para testar a unidade se o trabalho real de manter EXEs funcionará?

Meu pensamento inicial é iniciar um EXE falso que se fecha após 1 segundo e usá-lo para testar. Isso está fora do domínio dos testes de unidade?

MattW
fonte

Respostas:

12

Meu pensamento inicial é iniciar um EXE falso que se fecha após 1 segundo e usá-lo para testar. Isso está fora do domínio dos testes de unidade?

Este é um bom teste? Claro, então crie-o. É "um teste de unidade" no sentido real da palavra? Eu acho que não, eu chamaria isso de "teste do sistema" ou algo assim, mas isso não torna o teste menos valioso.

Doc Brown
fonte
9

Zombe de um nível superior a isso. Crie uma classe proxy Process.Start(), falsifique isso no teste e verifique as entradas.

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
        }
    }   
}

Sempre que você precisar consumir ClassUnderTest no código do aplicativo, use o construtor padrão. Nos seus testes, passe um FakeProcessProxy para o outro construtor, usando os parâmetros esperados de Início do Proxy e o resultado do teste no construtor do fake.

pdr
fonte
4

Ao seguir estritamente a filosofia de unittesting (ênfase na unidade ), você não deve criar um arquivo Exe, mas sim testar se sua classe chama as interfaces para gerar e monitorar o processo corretamente. Afinal, você deseja testar sua classe, não a biblioteca responsável pelo processamento do processo.

Mas de um ponto de vista pragmático, sua abordagem é boa, embora 1 segundo pareça um pouco longo.

keppla
fonte
1

Eu fiz algo semelhante, mas acabei de ligar ping localhost. Economiza o trabalho de colocar executáveis ​​em seu servidor de compilação

Ben
fonte