Pergunta

Eu sou mais convencido dos benefícios de testes de unidade, e eu gostaria de começar a aplicar o conceito a uma grande base de código existente escrito em PHP. Menos de 10% deste código é orientado a objetos.

Eu olhei várias estruturas de teste de unidade (PHPUnit, SimpleTest e HPTP). No entanto, eu não encontrei exemplos para qualquer um desses código processual que teste. Qual é a melhor estrutura para a minha situação e existem quaisquer exemplos de testes de unidade PHP usando o código não-OOP?

Foi útil?

Solução

Você pode unidade-teste PHP processual, não há problema. E você não está definitivamente fora de sorte se o seu código é misturado com HTML.

No nível do aplicativo ou aceitação de teste, seu PHP processual provavelmente depende do valor dos superglobals ($_POST, $_GET, $_COOKIE, etc.) para determinar o comportamento e as extremidades, incluindo um arquivo de modelo e cuspir para fora a saída.

Para fazer o teste de nível de aplicativo, você pode apenas definir os valores superglobais; iniciar um buffer de saída (para manter um monte de html de inundar sua tela); chamar a página; valer contra o material no interior do tampão; e o tampão de lixo no final. Então, você poderia fazer algo parecido com isto:

public function setUp()
{
    if (isset($_POST['foo'])) {
        unset($_POST['foo']);
    }
}

public function testSomeKindOfAcceptanceTest()
{
    $_POST['foo'] = 'bar';
    ob_start();
    include('fileToTest.php');
    $output = ob_get_flush();
    $this->assertContains($someExpectedString, $output);
}

Mesmo para enormes "quadros" com muita inclui, este tipo de teste vai dizer se você tem em nível de aplicativo apresenta funcionando ou não. Isso vai ser muito importante porque você começar a melhorar o seu código, porque, mesmo se você estiver convencido de que o conector de banco de dados ainda funciona e parece melhor do que antes, você vai querer clicar em um botão e ver que, sim, você ainda pode login e de logout através do banco de dados.

Em níveis mais baixos, existem pequenas variações dependendo escopo de variáveis ??e se as funções de trabalho de efeitos colaterais (retornando verdadeiro ou falso), ou devolver o resultado diretamente.

são variáveis ??passadas ao redor explicitamente, como parâmetros ou matrizes de parâmetros entre funções? Ou são variáveis ??definidas em muitos lugares diferentes, e passou implicitamente como globals? Se for o (a) caso explícito, você pode unidade de teste uma função por (1), incluindo o arquivo segurando a função, em seguida, (2) alimentando os valores dos testes de função diretamente, e (3) a captura a saída e afirmando contra ela. Se você estiver usando globals, você apenas tem que ser extremamente cuidadoso (como acima, no exemplo $ _POST) como nulo cuidadosamente todos os globals entre os testes. Também é especialmente útil para manter testes muito pequenos (5-10 linhas, 1-2 afirma) quando se tratar de uma função que empurra e puxa lotes de globals.

Outra questão básica é se as funções trabalhar, retornando a saída, ou alterando os parâmetros passados ??em, retornando verdadeiro / falso em seu lugar. No primeiro caso, o teste é mais fácil, mas, novamente, é possível em ambos os casos:

// assuming you required the file of interest at the top of the test file
public function testShouldConcatenateTwoStringsAndReturnResult()
{
  $stringOne = 'foo';
  $stringTwo = 'bar';
  $expectedOutput = 'foobar';
  $output = myCustomCatFunction($stringOne, $stringTwo);
  $this->assertEquals($expectedOutput, $output);
}

No caso ruim, onde o seu código funciona por efeitos colaterais e retorna verdadeiro ou falso, você ainda pode testar muito facilmente:

/* suppose your cat function stupidly 
 * overwrites the first parameter
 * with the result of concatenation, 
 * as an admittedly contrived example 
 */
public function testShouldConcatenateTwoStringsAndReturnTrue()
    {
      $stringOne = 'foo';
      $stringTwo = 'bar';
      $expectedOutput = 'foobar';
      $output = myCustomCatFunction($stringOne, $stringTwo);
      $this->assertTrue($output);
      $this->Equals($expectedOutput, $stringOne);
    }

Espero que isso ajude.

Outras dicas

O que testes de unidade faz bem, eo que você deve usá-los, é quando você tem um pedaço de código que você dá algum número de entradas, e você espera obter algum número de saídas recuar. A idéia é, quando você adicionar funcionalidades mais tarde, você pode executar os testes e verifique se ele ainda está realizando o velho funcionalidade da mesma forma.

Então, se você tem uma base de código processual, você pode fazer isso chamando as funções nos métodos de ensaio

require 'my-libraries.php';
class SomeTest extends SomeBaseTestFromSomeFramework {
    public function testSetup() {
        $this->assertTrue(true);
    }

    public function testMyFunction() {
        $output = my_function('foo',3);

        $this->assertEquals('expected output',$output);
    }
}

Este truque com bases de código PHP é, muitas vezes o seu código da biblioteca irá interferir com o funcionamento do seu framework de teste, como sua base de código e as estruturas de teste terá um monte de código relacionado com a criação de um ambiente de aplicação em um navegador web ( sessão, compartilhada variáveis ??globais, etc.). Espere gastar algum momento chegar a um ponto onde você pode incluir o seu código da biblioteca e executar um teste de sujeira simples (a função testSetup acima).

Se o seu código não tem funções, e é apenas uma série de PHP arquivos que páginas HTML de saída, você é tipo de fora da sorte. Seu código não pode ser separado em unidades distintas, que o teste de unidade meios não vai ser de muita utilidade para você. Você seria melhor fora de gastar o seu tempo no nível de "aceitação de testes" com produtos como selênio e Watir. Estes irão deixá-lo automatizado um navegador e, em seguida, verificar as páginas de conteúdo como locais específicos / em formas.

Você poderia tentar incluir o seu código não-oop em uma classe de teste usando

require_once 'your_non_oop_file.php' # Contains fct_to_test()

E com phpunit você define sua função de teste:

testfct_to_test() {
   assertEquals( result_expected, fct_to_test(), 'Fail with fct_to_test' );
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top