2009-05-22 4 views
28

나는 주로 단위 테스트의 이점에 대해 확신하고 있으며, PHP로 작성된 대형 기존 코드베이스에 개념을 적용하기 시작했습니다. 이 코드의 10 % 미만은 객체 지향적입니다.절차 적 코드베이스를 사용하여 PHP로 단위 테스트를 작성하려면 어떻게해야합니까?

몇 가지 단위 테스트 프레임 워크 (PHPUnit, SimpleTest 및 phpt)를 살펴 보았습니다. 그러나, 나는 절차 코드를 테스트하는 이들에 대한 예제를 발견하지 못했습니다. 내 상황에 가장 적합한 프레임 워크는 무엇이며 비 OOP 코드를 사용하는 PHP 단위 테스트의 예가 있습니까?

답변

34

절차 형 PHP를 단위 테스트 할 수 있습니다. 문제가 없습니다. 그리고 코드가 HTML과 섞여 있다면 확실히 운이 나지 않을 것입니다.

응용 프로그램 또는 수락 테스트 레벨에서 절차 용 PHP는 동작을 결정하기위한 수퍼 전역 변수 ($_POST, $_GET, $_COOKIE 등)의 값에 의존하고 템플릿 파일을 포함하고 출력을 내뱉어 끝냅니다.

응용 프로그램 수준 테스트를 수행하려면 수퍼 전역 값을 설정할 수 있습니다. 출력 버퍼를 시작하십시오 (html의 묶음을 화면에 넘치지 않게하십시오); 페이지를 호출하십시오. 버퍼 안의 것들에 대해 주장한다; 그리고 마지막에 버퍼를 지 웁니다. 그래서, 당신은 이런 식으로 뭔가를 할 수 :

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

비록 당신이 작동 여부 응용 프로그램 수준의 기능을 가지고있는 경우, 시험의 종류를 알려줍니다 포함이 많은 거대한 "프레임 워크"를 참조하십시오. 이것은 코드 개선을 시작할 때 매우 중요합니다. 왜냐하면 데이터베이스 커넥터가 여전히 작동하고 이전보다 훨씬 좋아 보이더라도 버튼을 클릭하여 볼 수 있습니다. 그렇습니다. 데이터베이스를 통한 로그인 및 로그 아웃.

하위 수준에서는 변수 범위 및 함수가 부작용 (true 또는 false 반환)으로 작동하는지 직접 결과를 반환하는지에 따라 사소한 차이가 있습니다.

변수가 함수 사이의 매개 변수 또는 매개 변수 배열로 명시 적으로 전달됩니까? 또는 변수가 여러 곳에서 설정되고 암시 적으로 전역 변수로 전달됩니까? 그것이 (좋은) 명백한 경우라면, (1) 함수를 포함하는 파일을 포함하여 함수를 단위 테스트하고, (2) 함수 테스트 값을 직접 입력하고, (3) 출력을 캡쳐하고 그것에 대해 어설트함으로써 함수를 단위 테스트 할 수 있습니다. 전역 변수를 사용하고 있다면 위의 $ _POST 예제와 같이 조심해서 모든 전역 변수를주의 깊게 무시해야합니다. 또한 많은 전역 변수를 밀고 당기는 함수를 처리 할 때 테스트를 매우 작게 유지하는 것이 특히 유용합니다 (5-10 행, 1-2 어설트).

또 다른 기본적인 문제는 함수가 출력을 반환하는지 또는 전달 된 매개 변수를 변경하여 true/false를 반환하는지 여부입니다. 첫 번째 경우, 시험은 쉽게, 그러나 다시, 그것은 두 경우 모두 가능 :

// 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); 
} 

코드가 부작용으로 작동 true 또는 false를 반환 나쁜 경우, 당신은 여전히 ​​아주 쉽게 테스트 할 수 있습니다 :

/* 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); 
    } 

희망이 있습니다.

+0

테스트중인 코드가'exit;'문으로 흩어져있는 경우에는 좋지 않습니다. ( –

+3

@ YarekT'exit' 또는'die' 문으로 코드가 흩어져있는 경우 테스트 할 수 없습니다. 예상 된 스크립트 종료를 처리하는 것은 예외를 throw하고 발생했을 때 사용자 정의 예외 유형을 무시할만큼 똑똑한 사용자 정의 예외 처리기를 등록하는 것입니다. 그런 다음 예상 된 예외가 발생했는지 테스트 할 수 있습니다 물론 물론 잘 설계된 응용 프로그램은 실제로 ' 어쨌든 부트 스트랩 단계 이후에 '종료'또는 '죽기'가 필요합니다. – rdlowrey

1
당신은
require_once 'your_non_oop_file.php' # Contains fct_to_test() 

그리고 phpunit을 가진

당신이 당신의 테스트 기능 정의를 사용하여 테스트 클래스로 비 OOP 코드를 포함하도록 시도 할 수

:

testfct_to_test() { 
    assertEquals(result_expected, fct_to_test(), 'Fail with fct_to_test'); 
} 
+0

이것은 흥미로운 솔루션처럼 보이지만 대부분의 논리가 함수를 포함하지 않고 단순한 루프와 조건문을 포함한다면 어떨까요? –

+5

그러면 스파게티 코드에 큰 도움이됩니다. –

+0

나는 Travis가 html로 PHP 코드를 가지고 있지 않다고 생각했다. –

6

어떤 단위 테스트는 잘하고, 무엇을 당신은 그들을 위해 사용해야합니다, 당신이 코드의 조각을 가지고 당신이 몇 가지 입력, 그리고 당신은 몇 가지 출력을 다시 얻을 것으로 기대하고있다. 나중에 기능을 추가 할 때 테스트를 실행하고 같은 방식으로 이전 기능을 계속 수행 할 수 있습니다. 당신은 절차 적 코드 기반을 가지고있는 경우

그래서, 당신은 PHP 코드베이스와이 트릭은 종종 라이브러리 코드가 실행을 방해한다

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

시험 방법이 호출하여 기능을 수행 할 수 있습니다 코드베이스와 테스트 프레임 워크는 웹 브라우저에서 응용 프로그램 환경 (세션, 공유 전역 변수 등)을 설정하는 것과 관련된 많은 코드를 갖기 때문에 테스트 프레임 워크의 일부입니다. 라이브러리 코드를 포함하고 간단한 간단한 테스트 (위의 testSetup 함수)를 실행할 수있는 지점에 언젠가는 들어가기를 기대하십시오.

코드에 기능이없고 HTML 페이지를 출력하는 일련의 PHP 파일 일 경우 운이 좋지 않습니다. 코드를 별개의 단위로 분리 할 수 ​​없으므로 단위 테스트가별로 유용하지 않습니다. SeleniumWatir과 같은 제품으로 "수락 테스트"수준에서 시간을 보내는 것이 좋습니다. 이것들은 당신에게 브라우저를 자동화 할 수있게 할 것이고, 그런 다음 양식들을 특정 위치/양식 들로서 페이지들을 체크 할 것입니다.

+0

코드를 명확하게 분리 할 수 ​​있습니다. 당신의 예제는 유망 해 보입니다. 이것은 특정 프레임 워크를 사용하지 않고 있습니다. –

+0

그래, 그건 단지 의사 테스트 코드 일 뿐이지 만 실제 SImpleTest 테스트와 PHPUnit 테스트는 현저하게 비슷해 보입니다. –

관련 문제