Trong TDD tôi nên viết Test trước hay Interface trước?


23

Tôi đang học TDD bằng cách sử dụng c #, theo như tôi biết kiểm tra sẽ thúc đẩy sự phát triển , đó là lần đầu tiên viết một bài kiểm tra thất bại sau khi viết mã tối thiểu để vượt qua bài kiểm tra sau đó thực hiện tái cấu trúc.

Nhưng người ta cũng nói rằng " Chương trình để giao diện, không phải thực hiện ", vì vậy hãy viết một giao diện trước . Đây là lúc sự nhầm lẫn của tôi bắt đầu, Nếu tôi viết Giao diện trước thì nó vi phạm hai điều

  1. Mã được viết cho giao diện không được điều khiển bằng thử nghiệm .

  2. Nó không phải là mức tối thiểu rõ ràng tôi có thể viết nó với một lớp đơn giản.

Tôi có nên bắt đầu bằng cách viết bài kiểm tra cho giao diện không? mà không thực hiện bất cứ điều gì tôi sẽ kiểm tra?

Nếu câu hỏi này nghe có vẻ ngớ ngẩn xin lỗi vì điều đó, nhưng tôi hoàn toàn bối rối. Có thể tôi đang dùng mọi thứ theo nghĩa đen.


8
"Chương trình cho một giao diện" có nghĩa là tách biệt những gì bạn cần từ một đoạn mã với cách nó được thực hiện. Nó không có nghĩa là sử dụng một interfacecho tất cả mọi thứ. A classcũng cung cấp một giao diện, bởi vì bạn có thể ẩn chi tiết triển khai trong privatecác biến.
Doval

@Doval, Có, bạn không cần giao diện cho mọi thứ, chỉ cần cái được gọi là a contract. Ví dụ, đây có thể ở dạng một lớp trừu tượng, mặc dù nó không phải là một lớp / phương thức ảo vì bạn không thể khởi tạo nó.
phân tích

2
TDD nói, "viết một bài kiểm tra thất bại." Một số TDDers nghiêm ngặt nói rằng nó được tính là "thất bại" nếu bạn không thể biên dịch thử nghiệm vì loại dữ liệu mà nó hoạt động chưa được khai báo.
Solomon chậm

Câu trả lời:


29

Vi phạm đầu tiên của bạn ("Mã được viết cho giao diện không được điều khiển bởi kiểm tra.") Không hợp lệ. Hãy sử dụng một ví dụ tầm thường. Giả sử bạn đang viết một lớp máy tính và bạn đang viết một thao tác bổ sung. Bài kiểm tra nào bạn có thể viết?

public class CalculatorTest {
    @Test
    public void testAddTwoIntegers() {
        Calculator calc = new Calculator();
        int result = calc.add(2, 2)
        Assert.assertEquals(4, result);
    }
}

Bài kiểm tra của bạn vừa xác định giao diện. Đó là addphương pháp, thấy không? addmất hai đối số và trả về tổng của chúng. Sau này bạn có thể xác định rằng bạn cần nhiều Máy tính và trích xuất một giao diện Java (trong trường hợp này) tại thời điểm đó. Các bài kiểm tra của bạn không nên thay đổi sau đó, vì bạn đã kiểm tra giao diện chung của lớp đó.

Ở cấp độ lý thuyết hơn, các bài kiểm tra là đặc điểm kỹ thuật thực thi cho một hệ thống. Các giao diện với một hệ thống nên được điều khiển bởi người dùng của hệ thống đó và các thử nghiệm là phương pháp đầu tiên bạn phải xác định các tương tác.

Tôi không nghĩ bạn có thể tách thiết kế giao diện khỏi thiết kế thử nghiệm. Xác định các tương tác và thiết kế các bài kiểm tra cho chúng là cùng một hoạt động tinh thần - khi tôi gửi thông tin này vào một giao diện, tôi mong đợi một kết quả nhất định. Khi có gì đó không đúng với đầu vào của tôi, tôi mong đợi lỗi này. Bạn có thể thực hiện công việc thiết kế này trên giấy và sau đó viết bài kiểm tra của mình từ đó hoặc bạn có thể thực hiện chúng cùng một lúc - điều đó không thực sự quan trọng.


2
+1 " Tôi không nghĩ bạn có thể tách biệt thiết kế giao diện khỏi thiết kế thử nghiệm " nên được in đậm, IMHO :)
Binary Worrier

Thậm chí còn dễ dàng hơn để hiển thị, nếu bạn muốn kiểm tra nhiều hơn một cách thực hiện chức năng, cho biết Nhập XML và Nhập CSV, bạn có thể kiểm tra chúng với cùng một phương thức từ cùng một giao diện mặc dù việc triển khai sẽ thay đổi. Hơn nữa, các bài kiểm tra thường liên quan đến một số chế nhạo và đối với giao diện này là cần thiết.
Walfrat

Bạn nói rằng bài kiểm tra không cần phải thay đổi, nhưng new Calculator()việc thực hiện có đúng không? Nếu có một triển khai mới cần thiết, có lẽ bạn sẽ thực hiện MultiplicationCalculator và bạn cần thay đổi thử nghiệm để sử dụng new AdditionCalculator()cho nó vẫn vượt qua? Hay tôi đang thiếu một cái gì đó?
Steve Chamaillard

3
@SteveChamaillard Chắc chắn, nếu thiết kế của bạn có bạn thay đổi tên lớp từ Máy tính thành AdditionCalculator, bài kiểm tra sẽ phải thay đổi để phù hợp. Tất nhiên, bằng cách thực hiện TDD, điều thực sự sẽ xảy ra là bạn sẽ thay đổi bài kiểm tra trước và thay đổi lớp sẽ theo sau để thực hiện bài kiểm tra.
Eric King

5

Chúng ta đang làm gì khi viết một interface? Chúng tôi đang viết mã, hay chúng tôi đang thiết kế?

Tôi không phải là người hâm mộ khái niệm Thiết kế hướng thử nghiệm, nhưng tôi thích Phát triển hướng thử nghiệm . Cá nhân tôi đã nhận được kết quả tốt nhất của mình khi tôi thiết kế lớp trước bằng cách thiết kế giao diện trước khi tôi viết bài kiểm tra. Tôi không tính giao diện là mã. Giao diện là một thiết kế mà tôi sẽ thực hiện bằng TDD. Nó có khả năng thay đổi một sự phát triển khi tôi làm việc, nhưng đó là lộ trình của tôi (cùng với danh sách thử nghiệm của tôi).

Tôi sẽ dừng lại trước khi tôi bắt đầu giận dữ, nhưng hy vọng đó là cách hữu ích để bạn nghĩ về nó.


4

Trong TDD tôi nên viết Test trước hay Interface trước?

Tất cả phụ thuộc vào cách bạn muốn làm TDD chính thống / tôn giáo .

Tôi đang học TDD

Vì bạn đang học, bạn nên thử nghiệm để có được một quy trình làm việc cá nhân, phù hợp với bạn.

  1. Nếu bạn muốn làm điều đó theo các cuốn sách , ban đầu bạn viết một bài kiểm tra, điều này rõ ràng sẽ thất bại, bởi vì bạn đang bắt đầu không có mã nào cả. Sau đó, bạn viết một số mã để thực hiện bài kiểm tra. Nếu điều đó được thực hiện, bạn có thể tự do cấu trúc lại mã hiện có, vì bạn có một bài kiểm tra cung cấp một số loại mạng an toàn cho tái cấu trúc. Quyết định sử dụng Giao diện là một số loại tái cấu trúc.

  2. Bên cạnh TDD hay không: Câu hỏi, có nên sử dụng giao diện hay không không thú vị ngay từ đầu. Tất nhiên, nếu bạn chắc chắn, bạn có hành vi khác nhau mà bạn muốn trải rộng trên một số đối tượng, thì nên suy nghĩ về việc sử dụng Giao diện: Ví dụ: nếu bạn có một loại đầu ra nào đó đến các đích khác nhau, sẽ rất hợp lý khi triển khai nó thông qua một giao diện Nhà văn và có các lớp khác nhau cho đầu ra ( FileWriter , Máy in , v.v.). Mặc dù đó là một câu nói phổ biến để viết lên một giao diện , nhưng điều đó không có nghĩa là: sử dụng một giao diện cho mọi thứ . Đôi khi nó là một mức độ gián tiếp đến nhiều. Btw. các dịch vụ cũng vậy. Nhưng đó là một chủ đề khác nhau.

  3. Mặt khác, bạn có thể phát triển hướng kiểm tra theo một cách khác: thiết kế mã của bạn để kiểm tra. Điều đó có nghĩa là, bạn viết mã, rất dễ kiểm tra - mặc dù bạn viết các bài kiểm tra sau đó . Sẽ không có vấn đề gì nếu bạn viết bài kiểm tra trước hoặc sau đó, miễn là bạn kiểm tra mọi cách.


5
Không thể đồng ý với điểm cuối cùng "Không thành vấn đề nếu bạn viết bài kiểm tra trước hoặc sau đó, miễn là bạn kiểm tra mọi cách". Nếu bạn tình cờ viết bài kiểm tra sau đó, bạn không thể chắc chắn liệu bài kiểm tra đó có kiểm tra đúng hay không.
k4vin

4
Như tôi đã nói ... Điều đó phụ thuộc vào mức độ chính thống của bạn ...
Thomas Junk

2

TDD hoặc BDD có nghĩa là Thực hiện giao diện tên miền của bạn trước và sau đó viết bài kiểm tra chống lại chúng theo cách giải thích của tôi. việc thực hiện giao diện có một hành vi dự kiến.

nó vẫn kiểm tra trước mã bởi vì giao diện không chứa logic có thể kiểm tra được, đó là cấu trúc bạn viết kiểm tra.

Tôi sẽ làm như sau

  1. Viết hành vi bán chính thức (Đưa ra: Khi nào: Sau đó :)

  2. Viết Giao diện (để lưu trữ phương thức đóng gói hành vi)

  3. Viết Kiểm tra mà nó xác định (nhập vào đã cho, gọi khi nào, kiểm tra sau đó)

  4. Viết / Thay đổi Bê tông (Lớp thực hiện giao diện) để vượt qua Bài kiểm tra


0

Không bao giờ viết bài kiểm tra trước khi bạn thiết kế giao diện. Khi bạn đang suy nghĩ về những loại bài kiểm tra để viết (thiết kế thử nghiệm), bạn cũng không nên đồng thời thiết kế (kiến trúc) ứng dụng của mình. Đừng nghĩ về hai điều cùng một lúc. Bạn đã nghe nói về sự tách biệt của mối quan tâm? Nó không chỉ áp dụng cho cấu trúc vật lý của mã mà còn cho quá trình suy nghĩ của bạn.

Quyết định cách ứng dụng của bạn nên được thiết kế đầu tiên. Điều này có nghĩa là bạn thiết kế giao diện của mình và mối quan hệ giữa các giao diện này. Cho đến khi bạn làm điều này, bạn không nên bắt đầu suy nghĩ về các bài kiểm tra. Khi bạn biết giao diện của mình là gì thì trước tiên bạn có thể tạo chúng và sau đó viết bài kiểm tra đối với chúng hoặc viết bài kiểm tra trước rồi tạo chúng. Trong trường hợp sau, rõ ràng bạn sẽ không thể biên dịch các bài kiểm tra. Tôi thấy không có hại cũng như bất kỳ sự vi phạm triết lý TDD nào trong việc tạo ra các giao diện trước khi thử nghiệm.


lý do trong câu trả lời hàng đầu có vẻ hấp dẫn hơn: "Tôi không nghĩ bạn có thể tách thiết kế giao diện khỏi thiết kế thử nghiệm. Xác định các tương tác và thiết kế thử nghiệm cho chúng là cùng một hoạt động tinh thần - khi tôi gửi thông tin này vào một giao diện, tôi mong đợi một kết quả nhất định . Khi có gì đó không đúng với đầu vào của tôi, tôi mong đợi lỗi này ... "
gnat

@gnat Tôi tin rằng Nissam ở đây đang đề cập đến interfacetừ khóa C # , không phải là thuật ngữ "giao diện" chung.
RubberDuck

@RubberDuck Tôi cũng nghĩ vậy và tôi tin rằng đây là một cách tiếp cận kém. "Cho đến khi bạn thực hiện điều này, bạn không nên bắt đầu suy nghĩ về các bài kiểm tra ..." Như tôi đã viết, lý luận trong câu trả lời hàng đầu có vẻ hấp dẫn hơn, cả về ý nghĩa chung của giao diện và theo nghĩa từ khóa cụ thể
gnat

Đủ công bằng @gnat mà không rõ ràng từ nhận xét của bạn. Cá nhân, tôi đồng ý với Nissam ở đây. Tôi thấy nó ngăn mọi người sử dụng TDD như một cái cớ để không thiết kế gì cả. YMMV.
RubberDuck

-2

Bạn có thể viết giao diện / mã / kiểm tra cùng một lúc miễn là sự kết hợp của họ vào dự án là nguyên tử.

Trừ khi ông chủ của bạn tôn giáo về TDD, trong trường hợp đó bạn có thể phải viết giao diện trống -> kiểm tra -> mã tối thiểu (bước vô nghĩa) -> nhiều kiểm tra hơn -> mã vô nghĩa hơn -> nhiều kiểm tra hơn -> cuối cùng viết mã thực - > xong.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.