2012-04-12 16 views
14

Tôi mới dùng thử nghiệm đơn vị và PHPUnit, nhưng tôi đã đọc rất nhiều về các mẫu thiết kế và kiểm tra riêng biệt và tôi đã quyết định tái cấu trúc ứng dụng mà tôi đang làm việc để loại bỏ các lớp tĩnh, singletons, hardcoded dependencies và bất cứ điều gì khác được định nghĩa trên phạm vi toàn cầu, hy vọng làm cho nó "testable" và không phải là một nỗi đau trong ass để mantain trong tương lai, vì nó có nghĩa là một dự án dài hạn. Cho đến nay tôi tin rằng tôi hiểu lý thuyết đằng sau thử nghiệm đơn vị, nhưng tôi đã tự hỏi, trong một kịch bản mà một đại biểu xử lý các phụ thuộc lồng nhau của các đối tượng vào một Nhà máy, làm thế nào để đi thử nghiệm đơn vị cho biết dư thừa để kiểm tra nó? Và cách tiếp cận tốt nhất để kiểm tra rằng "chuỗi" phụ thuộc hoạt động tốt trong đồng bộ là gì?Thực hiện thử nghiệm đơn vị với các phụ thuộc lồng nhau và các lớp Nhà máy

Hãy để tôi minh họa các câu hỏi. Giả sử bạn có các "di sản" đoạn mã sau:

class House { 
    protected $material; 
    protected $door; 
    protected $knob; 

    public function __construct() { 
     $this->door = new Door(); 
     $this->knob = $this->door->getKnob(); 
     $this->material = "stone"; 

     echo "House material: ".$this->material . PHP_EOL . "<br/>"; 
     echo "Door material: ".$this->door->getMaterial() . PHP_EOL . "<br/>"; 
     echo "Knob material: ".$this->knob->getMaterial() . PHP_EOL . "<br/>"; 
    } 
} 

class Door { 
    protected $material; 
    protected $knob; 

    public function __construct() { 
     $this->knob = new Knob(); 
     $this->material = "wood"; 
    } 

    public function getKnob() { 
     return $this->knob; 
    } 

    public function getMaterial() { 
     return $this->material; 
    } 

} 

class Knob { 
    protected $material; 

    public function __construct() { 
     $this->material = "metal"; 
    } 

    public function getMaterial() { 
     return $this->material; 
    } 
} 

$house = new House(); 

Đây là (theo như hiểu biết của tôi đi) xấu cho kiểm tra đơn vị, vì vậy chúng tôi thay thế các phụ thuộc hardcoded với DI + một lớp Factory:

class House { 
    protected $material; 
    protected $door; 
    protected $knob; 

    public function __construct($door) { 
     $this->door = $door; 
     $this->knob = $this->door->getKnob(); 
     $this->material = "stone"; 

     echo "House material: ".$this->material . PHP_EOL . "<br/>"; 
     echo "Door material: ".$this->door->getMaterial() . PHP_EOL . "<br/>"; 
     echo "Knob material: ".$this->knob->getMaterial() . PHP_EOL . "<br/>"; 
    } 
} 

class Door { 
    protected $material; 
    protected $knob; 

    public function __construct($knob) { 
     $this->knob = $knob; 
     $this->material = "wood"; 
    } 

    public function getKnob() { 
     return $this->knob; 
    } 

    public function getMaterial() { 
     return $this->material; 
    } 

} 

class Knob { 
    protected $material; 

    public function __construct() { 
     $this->material = "metal"; 
    } 

    public function getMaterial() { 
     return $this->material; 
    } 
} 

class HouseFactory { 
    public function create() { 
     $knob = new Knob(); 
     $door = new Door($knob); 
     $house = new House($door); 

     return $house; 
    } 
} 

$houseFactory = new HouseFactory(); 
$house = $houseFactory->create(); 

Bây giờ (và một lần nữa, theo như tôi hiểu) Nhà, Cửa và Núm có thể được kiểm tra đơn vị với phụ thuộc giả lập tốt. Nhưng:

1) Điều gì sẽ xảy ra với HouseFactory ngay bây giờ?

nên một chỉ:

  • Không kiểm tra nó vì nó không có bất kỳ logic ứng dụng giá trị thử nghiệm chưa và nhà máy thường ở lại như vậy. Giả sử rằng nếu kiểm tra độc lập cho Nhà, Cửa & Vượt qua Nhà máy sẽ ổn.
  • Tái cấu trúc nhà máy bằng cách nào đó, tức là sử dụng các hàm trong lớp để lấy từng cá thể theo cách sao cho có thể ghi đè các hàm này thông qua PHPUnit để trả về đối tượng giả, chỉ trong trường hợp có thêm một số logic trong lớp có thể sử dụng một số thử nghiệm trong tương lai.

2) Có khả thi để thiết lập các thử nghiệm dựa trên một số phụ thuộc (không được giả lập) cùng một lúc không? Tôi hiểu điều này về mặt kỹ thuật không phải là thử nghiệm đơn vị (thử nghiệm tích hợp có lẽ?) Nhưng tôi đoán nó vẫn hoàn toàn có thể thực hiện được bằng cách sử dụng PHPUnit? Với ví dụ trên, tôi muốn có thể thiết lập một bài kiểm tra không chỉ kiểm tra House, Door, Knob và HouseFactory trong sự cô lập, mà còn là kết quả của sự tương tác của các đối tượng thực với nhau, có lẽ với một số các chức năng được mô phỏng, chẳng hạn như các chức năng xử lý dữ liệu. PHPUnit có phải là lựa chọn tồi cho loại thử nghiệm này không?

Cảm ơn trước về thời gian của bạn. Tôi nhận ra một số giả định tôi đang làm có thể không chính xác, vì tôi rõ ràng không phải là một chuyên gia về vấn đề này; sửa đổi được hoan nghênh và đánh giá cao.

Trả lời

4

Nhà máy giống như từ khóa new. Bạn có kiểm tra từ khóa new không? Không, bạn kiểm tra xem bạn có thể xây dựng một lớp học không. Nhưng đó là độc lập với chính nhà máy và một phần của đơn vị như vậy đã là một phần của các bài kiểm tra đơn vị của bạn.

2) được gọi là kiểm tra tích hợp. Và bạn cũng có thể làm điều đó với PHPUnit.


Sửa - Như đã có một số cuộc thảo luận trong nhận xét:

Theo như thử nghiệm đơn vị có liên quan, bạn có thể đơn vị kiểm tra nhà máy của bạn mà nó cho những gì nó dành cho: trả lại loại bê tông, loại hoặc bất kỳ loại nào.

Không có gì sai với điều đó, tuy nhiên thường không cần thiết vì các nhà xây dựng của kiểu trả về đã được kiểm tra đơn vị và thử nghiệm đó thực sự tầm thường và chỉ kiểm tra dữ liệu có mùi thử nghiệm tích hợp. Ngoài ra những loại có loại đó từ nhà máy như phụ thuộc (và đó là theo đơn vị kiểm tra là tốt) sẽ làm cho biên dịch/thực hiện thất bại nếu phụ thuộc không thể được cung cấp. Vì vậy, tất cả mọi thứ nhà máy cho, đã được thử nghiệm, thậm chí từ cả hai bên. Và nếu nhà máy không bị tiêu thụ, thì bạn không cần phải kiểm tra nó.

Tôi khuyên bạn nên tạo một khi nhà máy thuần túy theo kiểu TDD, do đó, để chuẩn bị trước việc sử dụng và sau đó bạn sẽ có cảm giác về điều này. Bạn có thể muốn kiểm tra các khía cạnh khác của lớp nhà máy của bạn (es), nhưng có lẽ điều này thuộc về tích hợp hơn so với thử nghiệm đơn vị.

Và tôi không muốn tạo ấn tượng rằng các đơn vị khác của bạn nên thực sự có cuộc gọi được mã hóa cứng đến nhà máy tạo (các) phương pháp thay vì nhận phụ thuộc được tiêm. Vì bạn không nên sử dụng new bên trong các đơn vị của mình, bạn không nên sử dụng Factory::create trong đó. Tương tự như new, tên lớp (Factory) được mã hóa cứng, không được tiêm. Đó là một sự phụ thuộc ẩn rồi. Nhưng không nên ẩn phụ thuộc; nhưng được hiển thị.

+0

Nhà máy không giống như từ khóa 'mới'. Nó có thể được kiểm tra. 'HouseFactory :: create' nên làm gì? Nó tạo và * trả về * một 'House'. Bạn có thể và nên kiểm tra điều đó, hoặc với một bài kiểm tra đơn vị hoặc xác nhận với ít nhất. Ví dụ OP là đơn giản, nhưng nếu phương pháp của bạn có bất kỳ logic nào trong nó, nó sẽ được kiểm tra. – netcoder

+0

Ngoài ra, bạn không thể kiểm tra từ khóa 'mới' trong PHP (vì nó không phải là quá tải), nhưng bạn có thể quá tải nó trong C++ cho mỗi ví dụ, và bạn nên kiểm tra nó nếu bạn làm. – netcoder

+0

Vì hàm tạo của 'ngôi nhà' đã được kiểm tra đơn vị (theo TDD), không cần phải kiểm tra phương pháp nhà máy một cách bình thường. Bạn có thể kiểm tra tất cả mọi thứ, câu hỏi là nếu nó có ý nghĩa và thực sự là cần thiết. Kiểm tra tích hợp có thể bao gồm việc sử dụng của nhà máy và do đó bảo lãnh nếu nhà máy không phải là những gì nó đã được thực hiện cho. – hakre

0

Bạn có thể thử nghiệm bằng kế thừa.

Chỉ cần mở rộng Nhà có Nhà giả để thử nghiệm, sau đó kiểm tra tài liệu $, $ door và $ knob vv cho dù chúng đã thay đổi hay không sau khi thử nghiệm.

Các vấn đề liên quan