Tại sao nhanh nhẹn tất cả về phát triển dựa trên thử nghiệm (TDD) và không phải thử nghiệm theo hướng phát triển (DDT)?


74

Vì vậy, tôi mới bắt đầu nhanh nhẹn, nhưng không phát triển dựa trên thử nghiệm . Các giáo sư của tôi ở trường đại học đều có ý tưởng về các bài kiểm tra sau đó viết mã rồi kiểm tra. Tôi không chắc tại sao tôi hiểu. Theo quan điểm của tôi, rất nhiều chi phí trả trước rất có thể sẽ được thay đổi khi mã của bạn phát triển.

Đây là cách tôi tưởng tượng TDD và tại sao nó làm tôi bối rối. Nếu tôi xây nhà như một nhà thầu TDD.

  1. Hãy cho tôi tất cả các thông số kỹ thuật của bạn (câu chuyện).

  2. Nhận sự chấp thuận về thông số kỹ thuật.

  3. Chia nhỏ tất cả các thông số kỹ thuật thành kiểm tra Tôi nghĩ rằng tôi sẽ cần (xem trong tương lai).

  4. Gọi một thanh tra để xem xét các điểm đó và cho tôi biết ngay bây giờ tôi đang thất bại trong việc kiểm tra (cảm ơn).

  5. Bắt đầu xây nhà.

  6. Gọi thanh tra trở lại hàng ngày (qua 2/100).

  7. Ôi chao, có một vấn đề với sự hiểu biết của tôi và bây giờ tôi cần thêm 9 lần kiểm tra nữa và thay đổi 27 trong số chúng.

  8. Gọi thanh tra qua 1/109.

  9. Chết tiệt. Tại sao thanh tra không thích cái này ... ồ tôi đã cập nhật tên phương thức đó ...

  10. Xây dựng thêm một số.

  11. UGGGGHHHH THAY ĐỔI THÊM để tôi cập nhật thanh tra chết tiệt. Oh tôi đang thất bại không s ** t.

  12. Tôi đã xong chưa?

Được rồi, điều đó có thể kỳ quặc, nhưng tôi chỉ không thấy làm thế nào tôi nên biết tất cả các phương thức của mình và cách mọi thứ sẽ hoạt động cho đến khi mã của tôi ở đó. 99% thời gian tôi phải quay lại và cập nhật bài kiểm tra đơn vị bằng mọi cách và bổ sung thêm khi tôi đi. Nó chỉ có vẻ ngược.

Điều có vẻ phù hợp hơn là DDT hoặc thử nghiệm theo định hướng phát triển, đó là điều mà cộng đồng có tất cả nhưng quên mất về nó dường như.

Theo hiểu biết của tôi DDT cho một ngôi nhà sẽ như thế nào:

  1. Hãy cho tôi tất cả các thông số kỹ thuật của bạn (câu chuyện).

  2. Nhận sự chấp thuận về thông số kỹ thuật và phá vỡ chúng.

  3. Bắt đầu một đơn vị (nền tảng).

  4. Ghi chú (ý kiến) của một số logic khó khăn.

  5. Vào cuối trước khi bắt đầu, đơn vị tiếp theo có kiểm tra (tạo một bài kiểm tra).

  6. Khắc phục mọi sự cố được tìm thấy và kiểm tra lại.

  7. Đã phê duyệt đơn vị này chuyển sang tiếp theo.

Nếu tất cả chúng ta đều trung thực, điều đó nghe có vẻ nhân văn hơn và tập trung vào nhà phát triển và doanh nghiệp? Có vẻ như các thay đổi có thể được thực hiện nhanh hơn và dường như không có TDD trên cao.


60
Ngắt kết nối rõ ràng đối với tôi là ý tưởng rằng bạn có thể có hơn 100 bài kiểm tra thất bại trước khi viết mã bắt đầu vượt qua chúng. Như @Telastyn nói, không nên có nhiều hơn một vài bài kiểm tra thất bại tại một thời điểm. "Kiểm tra rồi Mã sau đó Kiểm tra" không có nghĩa là viết tất cả các thử nghiệm của ứng dụng trước khi viết bất kỳ mã nào.
Eric King

33
Phép ẩn dụ là một phản mẫu! Mọi người sẽ dành nhiều thời gian hơn để giải thích lý do tại sao phép ẩn dụ của bạn không phù hợp với chủ đề, thay vì giải quyết mối quan tâm thực sự của bạn. Trong trường hợp này, mối quan tâm thực sự của bạn dường như là bạn nghĩ rằng bạn phải viết tất cả các bài kiểm tra lên phía trước.
JacquesB

21
Như một lưu ý phụ ở đây, TDD thường được sử dụng trong các dự án nhanh nhưng tôi nghĩ điều quan trọng là phải phân biệt giữa quản lý dự án nhanh và thực hành phát triển nhanh. Không có mối quan hệ rất mạnh mẽ giữa hai người. Bạn có thể sử dụng hầu hết các thực tiễn phát triển nhanh nhẹn bất kể phương pháp dự án và ngược lại. Người ta thường quên rằng nhanh nhẹn, ở cốt lõi của nó, thực sự là về việc điều chỉnh cách tiếp cận của bạn khi cần thiết để đạt được kết quả tốt nhất chứ không phải về một danh sách quy định những việc bạn phải làm. Nói cách khác, Agile! = Scrum + TDD.
JimmyJames

35
Đối với hồ sơ, so sánh phát triển phần mềm để xây dựng một ngôi nhà là vô nghĩa. Các nghiên cứu đã được thực hiện. Kết quả là trong. Câu trả lời là rõ ràng. Bạn chỉ đơn giản là không xây dựng phần mềm giống như cách bạn xây dựng một ngôi nhà. Các. Hai. Được. Khác nhau.
riwalk

14
Agile là tất cả về các vòng phản hồi nhanh, TDD chỉ là một loại vòng phản hồi cụ thể
jk.

Câu trả lời:


83

Một trong những lợi ích của phương pháp TDD chỉ được nhận ra khi bạn cũng thực hiện thiết kế mới nổi.

Vì vậy, trong sự tương tự đầu tiên của bạn, bạn sẽ không viết 100 bài kiểm tra, vì không có cách nào bạn có thể biết phần mềm của bạn sẽ trông như thế nào.

Bạn viết một bài kiểm tra. Bạn chạy nó Nó thất bại. Bạn viết đơn vị mã nhỏ nhất để vượt qua bài kiểm tra của bạn. Sau đó, bạn chạy thử nghiệm của bạn một lần nữa. Nó đi.

Bây giờ viết bài kiểm tra tiếp theo, lặp lại quá trình trên.

Điều này có vẻ như là một cách tiếp cận lãng phí ngay từ đầu, khi rõ ràng mã của bạn có ý nghĩa gì, nhưng điều tuyệt vời với cách tiếp cận này là phạm vi kiểm tra của bạn luôn cao và thiết kế mã sạch hơn theo cách này.

Như một phương pháp, nó đi đôi với lập trình cặp; Một cặp viết bài kiểm tra, người tiếp theo viết mã để vượt qua, sau đó viết bài kiểm tra tiếp theo, v.v.

Tôi thậm chí sử dụng phương pháp này khi viết một lớp mới; thử nghiệm đầu tiên là một cuộc gọi để khởi tạo hàm tạo lớp. Nhưng tôi chưa viết lớp, nên thất bại. Tiếp theo tôi viết lớp đơn giản, trống rỗng, và bài kiểm tra đầu tiên của tôi đã vượt qua.

Một khi bạn đi vào suy nghĩ, sẽ rất khó để không ở trong đó và viết mã theo cách "lỗi thời".

Tôi khuyên bạn nên làm việc trong môi trường Agile tốt để tìm hiểu điều này hoặc đọc một vài cuốn sách Agile tốt (Clean Code và Clean Coder đều rất tốt) để hiểu rõ hơn.


46
Thuật ngữ "Thiết kế mới nổi" nghe có vẻ như bạn có thể phát triển một thiết kế phần mềm bằng cách thực hiện các bài kiểm tra. Bạn không thể.
Robert Harvey

28
@nerdlyist: Mặc dù vậy, đừng quên thiết kế. Bạn vẫn cần thiết kế phần mềm; thiết kế tốt không tự nhiên xuất hiện từ tái cấu trúc đỏ-xanh. TDD khuyến khích thiết kế tốt, nhưng nó không tạo ra nó.
Robert Harvey

19
@RobertHarvey, tôi hoàn toàn không đồng ý với " Thuật ngữ" Thiết kế mới nổi "của bạn có vẻ như bạn có thể phát triển một thiết kế phần mềm bằng cách thực hiện các bài kiểm tra vượt qua. Bạn không thể " tuyên bố. Đã làm điều đó trong một số dịp, tôi có thể đảm bảo với bạn rằng nó có thể được thực hiện.
David Arno

12
@DavidArno: Bạn có bắt đầu với một đặc tả yêu cầu trong tay không? Làm thế nào để bạn dịch đặc tả đó thành một kiến ​​trúc hợp lý? Bạn có phát minh lại nó mỗi lần với các bài kiểm tra, hoặc bạn có các nguyên tắc kiến ​​trúc trước đó trong tâm trí không? Không ai làm điều này trong mù; Không có gì kỳ diệu về việc viết bài kiểm tra của bạn trước, ngoài việc nó buộc bạn phải làm cho mã của mình dễ kiểm tra hơn.
Robert Harvey

45
@DavidArno Tôi nghĩ rằng sự phản đối của bạn bắt nguồn từ việc không cho mình đủ tín dụng như một nhà phát triển / kiến ​​trúc sư giàu kinh nghiệm. Vì bạn đã biết mô-đun X trông như thế nào bằng trực giác , các bài kiểm tra của bạn sẽ thúc đẩy sự phát triển của bạn theo hướng tốt. Một nhà phát triển thiếu kinh nghiệm có ít hoặc không có khái niệm trực quan về mô-đun sẽ trông như thế nào trước khi viết các bài kiểm tra sẽ xây dựng một mô-đun crappy được thử nghiệm tốt.
Svidgen

86

Phần mềm không phải là một ngôi nhà. Trực giác là tốt, nhưng hiểu rằng nó không phải lúc nào cũng đúng.

Chia nhỏ tất cả các thông số kỹ thuật thành kiểm tra Tôi nghĩ rằng tôi sẽ cần (xem trong tương lai).

Điều này không chính xác. Trong TDD, bạn đang mô tả cách bạn muốn sử dụng mã. Thông số kỹ thuật cho biết "Phải có một ngôi nhà, với một cách để vào nó." Bài kiểm tra sau đó cho biết "Này, tôi muốn có một cửa trước, với một núm." Đây là xa ít khi nhìn thấy trong tương lai vì bắt đầu với việc thực hiện xây dựng một khung cửa, núm, khóa phím, vv (hoặc lâu hơn đối số đi).

Gọi thanh tra trở lại hàng ngày (qua 2/100).

Điều này không đúng. Bạn không viết bài kiểm tra cho ngôi nhà. Bạn đang viết bài kiểm tra cho khung cửa trước, sau đó làm cho chúng có màu xanh. Sau đó kiểm tra cửa có chắc chắn không, làm cho chúng có màu xanh. Bạn có thể có hàng tá các bài kiểm tra ít nhất bị hỏng tại bất kỳ thời điểm nào. Thông thường, nó gần với hai đến bốn.

Ngoài ra, sự tương tự "gọi thanh tra ra" ngụ ý rằng phải mất một khoảng thời gian để người đó ra ngoài và thực hiện công việc của họ. Chạy thử nghiệm đơn vị cho một lần lặp TDD theo nghĩa đen sẽ mất vài giây.

Có vẻ như các thay đổi có thể được thực hiện nhanh hơn và dường như không có TDD trên cao.

Chi phí thấp hơn bạn dường như đang ám chỉ. Một vài giây để chạy các bài kiểm tra có thể một nửa tá lần là không quan trọng với thời gian phát triển chung.

Vấn đề của dev đầu tiên là đôi khi khi bạn đi kiểm tra, bạn phát hiện ra rằng có một vấn đề lớn . Giống như bạn đặt giường cạnh nhà vệ sinh và không ai muốn sống ở đó. Những thứ mất nhiều thời gian để sửa hơn bất kỳ loại TDD nào. Những điều mà TDD sẽ bắt được, vì TDD buộc bạn phải sử dụng mã của mình ngay từ đầu và suy nghĩ về cách giao diện với nó.

Các giáo sư của tôi ở trường đại học đều nói về ý tưởng Kiểm tra rồi Mã rồi Kiểm tra.

Tất cả những gì đã nói, TDD không phải là phổ biến. Nhiều nơi vẫn phát triển đầu tiên và phần lớn lợi ích có mục đích của TDD bị che lấp. Điều quan trọng là bạn thực hiện các bài kiểm tra và làm cho chúng tốt. Thứ tự mà bạn làm công việc ít quan trọng hơn.


18
+1 chỉ cho đoạn cuối cùng. Các ví dụ ngôi nhà của bạn thực sự làm nổi bật cách "tôn giáo" ngớ ngẩn có thể.
Robert Harvey

23
"Điều quan trọng là bạn thực hiện các bài kiểm tra và làm cho chúng tốt. Thứ tự mà bạn thực hiện công việc ít quan trọng hơn. " Tôi là một fan hâm mộ lớn của Test-Driven-Development (TDD) và thường xuyên ủng hộ nó. Tuy nhiên viết mã thì lộn xộn. Đối với các vấn đề khó hơn, ít được xác định rõ hơn, tôi thường phải viết một số mã trước khi tôi có thể hiểu các yêu cầu là gì. Sau đó tôi có thể viết các yêu cầu và sau đó viết các bài kiểm tra.
Trevor Boyd Smith

1
@TrevorBoydSmith bạn sẽ không viết tài liệu vào thời điểm đó không phải là yêu cầu.
mọt sách

8
Vì TDD đặt trong viễn cảnh của người sử dụng mã, [trong trường hợp tốt nhất], nó thúc đẩy các giao diện tốt hơn. Ví dụ, khi tôi gọi open_doortôi không nên truyền cờ cho toilet_flushed; vì vậy tôi không viết bài kiểm tra của mình theo cách đó và do đó mã của tôi không có những "cạnh thô" này. Mã được viết hoàn toàn mà không quan tâm đầy đủ đến cách nó được gọi thường có các giao diện hoặc giả định / điều kiện tiên quyết kỳ lạ.
brian_o

3
@TrevorBoydSmith để đặt tên cho nó, tôi đã nghe cái gọi là "Spike & Ổn định" và vâng, đó là một kỹ thuật tiện dụng khi khám phá cách làm điều gì đó mà bạn chưa biết cách làm.
RubberDuck

13

Sự tương đồng giữa việc xây dựng một vật lý và phần mềm viết là khá tối thiểu.

Điều đó nói rằng, có một sự khác biệt lớn đáng để chỉ ra:

Có một sự khác biệt giữa "tác giả một bài kiểm tra" và "thực hiện một bài kiểm tra."

Trong ví dụ về xây dựng một ngôi nhà, các yêu cầu và thử nghiệm được thực hiện trước khi xây dựng vật lý. Và các phần của bộ thử nghiệm được chạy liên tục - thậm chí bởi nhiều tác nhân! Khi người xây dựng nhặt được 2x4, anh ta ngay lập tức và tự động "kiểm tra" thiết bị dựa trên quan niệm của mình về "âm thanh của 2x4 trông như thế nào". Anh ta không yêu cầu tác giả sau khi anh ta nhặt nó lên; ông chạy kiểm tra trước đó trên nó.

Tương tự như vậy đối với một bức tường lắp ráp, một hộp điện, hệ thống ống nước, vv - các thử nghiệm / yêu cầu đã tồn tại; họ được chạy ngầm và tự động bởi con mắt được đào tạo của mọi người trong công việc liên tục . Một bộ thử nghiệm tiền tồn tại khác được thực hiện khi thanh tra đến thăm. Nếu các đơn vị không được xây dựng để vượt qua những pre-existent kiểm tra, họ thất bại.

Và tương tự như vậy cho các cấu trúc nói chung. Các kế hoạch tồn tại trước khi xây dựng. Ở mỗi bước đi, các kỹ sư đang làm việc hướng tới một tập hợp các điều kiện tồn tại trước đó mà cấu trúc cuối cùng sẽ được kiểm tra khi quá trình xây dựng hoàn tất.

Điều đó nói rằng, không phải mọi dự án vật lý cần phải được đi trước bởi một bộ thử nghiệm khổng lồ. Nếu bạn đi đến xưởng của bạn và bắt đầu ghép gỗ lại với nhau cho một hộp đồ chơi hoặc thứ gì đó, hãy để trực giác và sự sáng tạo của bạn hướng dẫn bạn, đó không phải là nghề mộc TDD khắt khe. Trong trường hợp đó, về cơ bản, bạn dựa vào các quy luật vật lý của phương tiện và những kỳ vọng khó khăn của bạn để xác nhận công việc (nghĩa là "nếu nó biên dịch và nó hoạt động, thì tốt!").

Và điều đó ổn. Không phải tất cả mọi thứ cần phải được đi trước bởi các bài kiểm tra nghiêm ngặt.

tl; dr

Mặc dù xây dựng! = Phần mềm viết: Xây dựng hoạt động theo kiểu thử nghiệm. Các điều kiện "vượt qua" cho mọi đơn vị trước khi xây dựng.

Đừng kết hợp "thực hiện kiểm tra" với "kiểm tra viết".

Không phải tất cả mọi thứ cần phải là TDD.


Tôi nhận được mã! = Vật lý của nó là một sự tương tự. Nhưng điều này thực sự làm sáng tỏ thêm một chút cho tôi. Như bình luận khác của tôi chỉ ra tôi đang tự hỏi liệu điều này tạo ra bài kiểm tra đầu tiên có cản trở mong muốn quay trở lại và thực hiện những thay đổi lớn hơn bây giờ không?
mọt sách

@nerdlyist Theo một cách nào đó, vâng. Nhưng, nếu các bài kiểm tra của bạn đang kiểm tra những điều "đúng", thì đó là "sự cản trở" mà bạn muốn .
Svidgen

4
Quay trở lại sự tương tự ngôi nhà: Nếu khách hàng của bạn đột nhiên muốn trao đổi theo một kiểu cửa khác và nó không có cùng kích thước, các yêu cầu xung quanh cửa và kích thước mở sẽ thay đổi và công việc yêu cầu thay đổi các "thử nghiệm" đó "Nên phản ánh công việc cần thiết để thực hiện thay đổi. Nhưng, có rất nhiều thử nghiệm sẽ không thay đổi: Cửa phải mở và đóng, khóa và được P% kín khí khi mở khi đóng, v.v ... Rất nhiều thử nghiệm không thay đổi "cản trở" thay đổi vật lý một cách thích hợp .
Svidgen

1
Nếu tôi có thể +1 lần nữa, tôi sẽ cân nhắc điều đó một chút. Không phải tất cả mọi thứ cần một bài kiểm tra. Ngoài ra, đọc lại nó làm tôi nghĩ có lẽ tôi đang hợp nhất các bài kiểm tra đơn vị TDD với kiểm tra tích hợp và hồi quy. Các công nhân tự động kiểm tra là các đơn vị mà thanh tra là tích hợp và kiểm tra hồi quy được thực hiện khi thực hiện các thay đổi lớn hơn.
mọt sách

1
@nerdlyist Các bài kiểm tra tích hợp và hồi quy cũng có thể được thực hiện trước tiên. Làm như vậy không hoàn toàn phù hợp với chu trình phát triển "giáo điều giáo điều TDD", nhưng kết quả phần lớn giống nhau: Bạn kết thúc với mã có thể kiểm tra, với mã ngoại lai tối thiểu và các thử nghiệm xác thực những gì họ yêu cầu. Kiểm tra sau khi bạn viết mã có thể làm cho việc hoàn thành bất kỳ hoặc tất cả những điều đó trở nên khó khăn hơn một chút. Không phải là không thể, nhưng có khả năng khó khăn hơn.
Svidgen

11

Bạn đã rơi vào cái bẫy tin vào ý tưởng vô nghĩa rằng viết phần mềm tương tự như xây dựng một ngôi nhà. Không phải vậy. Nó tương tự hơn để tạo ra các bản vẽ kiến ​​trúc sư và các tính toán kỹ sư kết cấu.

Bây giờ với những ngôi nhà thực sự, kiến ​​trúc sư tạo ra những kế hoạch lên phía trước. Sau đó, bạn gọi các nhà xây dựng, những người bắt đầu xây dựng, gặp vấn đề, phải sửa đổi mọi thứ, kiểm soát tòa nhà, ai muốn thay đổi, v.v ... Cuối cùng, kiến ​​trúc sư quay lại và tính phí cho bạn nhiều hơn để cập nhật bản vẽ của mình để phản ánh Chuyện gì đã xảy ra. Đây là một cách làm việc nhảm nhí, nhưng nhà cửa mất nhiều thời gian để xây dựng và tốn kém, vì vậy đó là cách thực tế duy nhất.

Mọi thứ tốt hơn cho công nghệ phần mềm. Tương đương với việc xây dựng ngôi nhà đang có trình biên dịch biến mã của bạn thành một đơn vị được biên dịch thuộc loại nào đó (thư viện, ứng dụng, ứng dụng web, v.v.). Nó rất nhanh và rẻ để làm điều này hàng trăm lần một ngày. Kết quả là, sẽ vô nghĩa khi liên tục xây dựng lại ngôi nhà khi bạn thêm các tính năng và chỉ gọi người kiểm tra (QA) ở cuối để kiểm tra nó. Thay vào đó, nếu bạn tự động hóa các kiểm tra đó, bạn có thể yêu cầu thanh tra kiểm tra lại mọi thứ mỗi khi bạn xây dựng lại.

Cho dù bạn tuân theo TDD nghiêm ngặt, hay cách tiếp cận theo hướng kiểm tra hơn là viết một số mã, thì một số thử nghiệm, không thực sự quan trọng. Tôi thích cách tiếp cận đầu tiên, những người khác sau. Chọn một trong những phù hợp với bạn. Điều quan trọng là bạn tạo ra những kiểm tra khi bạn đi cùng. Họ sẽ giúp đỡ sau này khi bạn muốn thay đổi mã xung quanh bằng cách cảnh báo bạn về sự phá vỡ chức năng ở nơi khác khi bạn thay đổi điều gì đó.


1
Tôi thấy bạn đã xử lý Kiểm soát tòa nhà rồi ... :)
Jules

5
"Đây là một cách làm việc nhảm nhí, nhưng nhà cửa mất nhiều thời gian để xây dựng và tốn kém, vì vậy đó là cách thực tế duy nhất.": Đúng là trong phần mềm bạn có thể xây dựng lại rất nhanh, nhưng nếu bạn làm sai hoàn toàn quyết định lúc đầu bạn có thể cần viết lại lớn sau này. Thiết kế gia tăng không phải lúc nào cũng gặp phải loại vấn đề này: bạn di chuyển theo từng bước nhỏ cho đến khi bạn thấy mình rơi vào tình trạng khó khăn và bạn phải quay lại. Không có viên đạn bạc.
Giorgio

2
@Giorgio - việc viết lại lớn xảy ra vì các quyết định đơn lẻ được phản ánh ở nhiều nơi trong mã. Khi quyết định thay đổi, sau đó mã thay đổi ở rất nhiều nơi. Tái cấu trúc liên tục giảm thiểu vấn đề này, bằng cách vắt kiệt sự trùng lặp và giới hạn số lượng mã phản ánh một quyết định. Bảo hiểm thử nghiệm tốt hỗ trợ tái cấu trúc liên tục.
kevin cline

7

Đầu tiên và quan trọng nhất là chi phí trả trước không cao như bạn nghĩ . Có, bạn dành nhiều thời gian để giải quyết việc kiểm tra hơn là nếu bạn không kiểm tra. Nhưng nếu bạn thực hiện phương pháp "kiểm tra sau" thì bạn thực sự lãng phí điều gì? Giả sử TDD mất 10 giờ và DDT mất 6 giờ. Chi phí trả trước "thêm" của bạn chỉ 4 giờ. Bây giờ nếu bạn áp dụng một số liệu mã hoặc yêu cầu như bảo hiểm 90%, thì TDD và DDT của bạn sẽ trở nên gần gũi hơn về chi phí.

Bạn sẽ viết mã lỗi ít hơn với TDD. Ngay cả khi đó chỉ là do bạn đã đánh vần các yêu cầu dưới dạng thử nghiệm, vào cuối ngày bạn có thể chứng minh rằng mã của bạn đang thực hiện chính xác những gì bạn muốn nó làm. Bây giờ có lẽ bạn muốn nó làm sai, nhưng đó không phải là lỗi mà là yêu cầu thay đổi. Điều này quan trọng. Việc "bán" một sản phẩm đang hoạt động dễ dàng hơn, nhưng có thể hoạt động khác / tốt hơn, sau đó là bán một sản phẩm được coi là không hoạt động. Với TDD, theo nghĩa đen là không thể vượt qua bài kiểm tra và viết mã không hoạt động. Có thể bạn không hiểu các yêu cầu và bạn đã viết sai, nhưng mã làm việc.

TDD càng tốt thì cơ sở mã càng cũ. Hãy thử tái cấu trúc mà không có bộ kiểm tra hoặc với bộ được triển khai kém. Ngay cả một thay đổi đơn giản cũng có thể giới thiệu lỗi. Có một bộ thử nghiệm với độ bao phủ tốt đảm bảo rằng khi sản phẩm phát triển, nó tiếp tục hoạt động như bình thường. Nó cũng giúp làm nổi bật các quy tắc kinh doanh mâu thuẫn (xảy ra trong thời gian dài hơn).

Bạn không biết nó không hoạt động. Nếu không có bộ kiểm tra, bạn không biết liệu mã của mình có hoạt động theo cách bạn nghĩ hay không, nếu nó chỉ hoạt động.

var foo = function(in) {
    if(in == 0) {
      return true
    }
}

Bây giờ trên tất cả các ứng dụng của bạn, bạn gọi if(foo()){ doStuff() }Điều gì xảy ra khi tôi sửa lỗi foo?

var foo = function(in) {
    if(in === 0) {
      return true
    }
}

Bạn cũng nên tái cấu trúc và DRYing các bài kiểm tra của bạn. Một bộ kiểm tra tốt không khó để duy trì. Với các bài kiểm tra nguyên tử được viết tốt, tôi hiếm khi phải quay lại và thay đổi hơn 1-2 trong số chúng cùng một lúc. Khi có những thay đổi lớn hơn đối với bộ thử nghiệm, đó là một lá cờ đỏ khổng lồ có gì đó không đúng.

Tôi chỉ không thấy làm thế nào tôi nên biết tất cả các phương thức của mình và cách mọi thứ sẽ hoạt động cho đến khi mã của tôi ở đó.

Chà, bạn không được phép. Bạn phải viết một bài kiểm tra để kiểm tra xem một số đơn vị công việc đã được thực hiện. Nếu bạn cảm thấy như bạn đang thử nghiệm những điều mà bạn không thể biết thì bạn đang nghĩ quá lớn, HOẶC thử nghiệm quá nhỏ.

Ví dụ, bạn cần biết rằng một cánh cửa đóng lại và khóa. Tôi sẽ kiểm tra door.close () và door.lock () và cửa đó.open () trả về false khi cửa bị khóa. Thế là xong. Nếu các kiểm tra của bạn là door.lock () sẽ đặt cờ trong cơ sở dữ liệu. Sau đó, bạn đang thử nghiệm quá nhỏ. Bài kiểm tra không cần biết cách hoạt động của door.lock (), chỉ có vậy thôi.

Bây giờ nếu bạn đang viết một bài kiểm tra cho biết house.isSecure () trả về đúng khi tất cả các cửa và cửa sổ bị khóa. Không nhìn vào cửa ra vào hoặc cửa sổ trước thì bạn đang nghĩ quá lớn.

Cuối cùng, bạn có thể đang nhìn vào một đơn vị công việc quá lớn . Khi bạn nhận được danh sách các yêu cầu của mình, bạn nên sắp xếp chúng để bạn làm việc trên đơn vị nhỏ nhất. Viết bài kiểm tra cho đơn vị đó, sau đó mã, sau đó rửa sạch và lặp lại.

Về bản chất, sự hiểu biết của bạn (danh sách) về cách TDD nên hoạt động là tắt. Bạn không bao giờ nên có 2/100 đi qua. Bạn nên có 1/1 đi qua, sau đó 2/2 đi qua, rồi 3/3 đi qua, rồi 4/4 đi qua, v.v.

Một danh sách sửa đổi cho bạn

  1. Nhận tất cả các thông số kỹ thuật
  2. Chọn một đặc điểm kỹ thuật
  3. Kiểm tra nó
  4. Mã nó
  5. Kiểm tra nó
  6. Nếu kiểm tra vượt qua chuyển sang 7 khác đi đến 4
  7. Nếu bạn đã thực hiện tất cả các thông số kỹ thuật, đi đến 8 khác đi đến 2
  8. Xem xét các thông số kỹ thuật với người tiêu dùng và thêm thông số kỹ thuật mới khi cần thiết. Nếu được thực hiện chính xác, bạn không cần phải thay đổi bất kỳ bài kiểm tra nào. Chỉ cần thêm những cái mới. Đôi khi việc thu thập các yêu cầu có thể sụp đổ và bạn phải thêm các bài kiểm tra mâu thuẫn với các bài kiểm tra trước đó, nhưng bạn hiếm khi phải thay đổi các bài kiểm tra.

2
Tôi thích câu trả lời này vì nó làm nổi bật những lợi thế thực sự của TDD - làm cho các cơ sở mã di sản có thể quản lý được. Nhiều người chỉ làm việc trong giai đoạn sân xanh của dự án không thấy được lợi ích của TDD vì có vẻ như đó chỉ là công việc làm thêm. Nó thực sự được đền đáp khi bạn phải nâng cấp và duy trì một cơ sở mã hiện có. Tôi ước rằng ở trường họ sẽ cung cấp cho bạn một dự án, ngay sau khi bạn nhận được nó, hãy yêu cầu một loạt các thay đổi tính năng. Điều đó sẽ phản ánh chặt chẽ hơn thực tế và chứng minh giá trị của TDD.
thomij

1
Tôi cũng thích câu trả lời này. Lưu ý rằng chúng ta có xu hướng quên mất chúng ta thực sự dành bao nhiêu thời gian để thực hiện các bài kiểm tra thủ công: chỉnh sửa, biên dịch, từng bước để gỡ lỗi thủ công, lặp lại. TDD tự động hóa phần lớn điều này.
Technophile

Điều làm tôi ngạc nhiên ở đây là điều quan trọng cần lưu ý là khi bạn viết một bài kiểm tra đơn vị trong TDD, bạn không viết một bài kiểm tra cho một phần của thông số chức năng của máy khách, bạn đang viết một bài kiểm tra cho hành vi của đơn vị như bạn - một lập trình viên - đã định nghĩa nó trong não của bạn, tức là "lớp này sẽ đưa ra một sự kiện khi X xảy ra, hãy viết một bài kiểm tra cho điều đó." Điều này mơ hồ "các bài kiểm tra của bạn là thông số kỹ thuật của bạn!" hùng biện là tuyệt vời khi bạn đã nhận được TDD nhưng với một người nào đó thoát khỏi vòng lặp, nó đặt ra nhiều câu hỏi hơn là câu trả lời.
Ant P

4

Có một số chìa khóa mà tôi cảm thấy các câu trả lời khác bị thiếu.

Ba lợi thế

Đầu tiên, chi phí lỗi và chi phí thay đổi là vô cùng khác nhau giữa phần mềm và ngôi nhà mà một số quy tắc có thể không áp dụng. Ví dụ, chi phí kiểm tra một cấu trúc vật lý cao đến mức bạn cần một mức độ tự tin cao về nó hoạt động để không lãng phí kiểm tra. Với phần mềm, nếu bạn có thể chạy một bộ các bài kiểm tra đơn vị trong 1 - 5 giây, thì chúng tôi có các tùy chọn khác nhau theo ý của chúng tôi.

Thứ hai, mục đích của việc thực hiện một thử nghiệm mà bạn dự kiến ​​sẽ thất bại trước khi viết thử nghiệm dưới mã là để xác minh thử nghiệm đó. Chắc chắn nó có vẻ ngớ ngẩn hoặc lãng phí. Nhưng tôi đã thấy đủ các bài kiểm tra đơn vị được viết theo cách sẽ luôn vượt qua, ngay cả khi bài kiểm tra dưới mã bị hỏng. Điều đó có thể dễ dàng xảy ra khi bạn viết bài kiểm tra mã, kiểm tra thủ công, sau đó viết bài kiểm tra đơn vị. Nếu bạn viết một bài kiểm tra đơn vị, thấy nó thất bại, thì khi bạn viết mã cần thiết để làm cho nó vượt qua, và nó vượt qua, bạn biết bài kiểm tra của bạn là âm thanh. Nếu hồi quy kiểm tra mã, có khả năng hợp lý bài kiểm tra đơn vị của bạn sẽ bắt được nó.

Một lợi thế thứ ba đối với TDD, không thường được đề cập, là kích thước và độ phức tạp của mã kết quả thường là một thứ tự nhỏ hơn. Tôi luôn tự hào về việc thích mã đơn giản và súc tích. Cho đến khi tôi bắt đầu thực hành TDD. TDD cho tôi thấy rằng những gì tôi đã làm trước đó sẽ là mã quá mức. Lý do tại sao điều này xảy ra? Bởi vì bạn viết một bài kiểm tra, sau đó viết mã để thực hiện bài kiểm tra. Khi bài kiểm tra trôi qua, bạn đã hoàn thành nó. Nếu bạn đang ở trong tâm trí này, thật khó để vô tình viết mã "phụ".

(Mã bổ sung đã là một vấn đề tôi đã quan sát thấy trong một sản phẩm tôi từng làm việc. Các vấn đề nghiêm trọng đến từ mã mà không ai yêu cầu, nhưng một số nhà phát triển nghĩ rằng nó sẽ rất tuyệt.)

Phân tích chi phí

Vì vậy, trong một số cách, bạn là đúng. Chúng tôi không thể thoát khỏi chiến lược này khi xây dựng một ngôi nhà. Nó sẽ là quá đắt. Nhưng phần mềm không phải là một ngôi nhà. Phần mềm rẻ.

Sự tương đồng với một ngôi nhà là công sức lắp ráp ngôi nhà so với trình biên dịch phần mềm.

Trong một thế giới không TDD, các nhà phát triển vẫn lặp đi lặp lại. Chúng tôi theo một mã -> biên dịch -> chạy -> chu kỳ kiểm tra. Chúng ta đang ở trong một mô hình đi chệch khỏi việc xây dựng một ngôi nhà. Nếu người xây dựng của bạn xây dựng khung cửa, sau đó xây dựng cửa, sau đó phải xây dựng lại khung vì cửa quá lớn đối với nó, bạn sẽ gặp vấn đề về chi phí. Do đó, bạn dành nhiều thời gian hơn để đảm bảo bạn có được mọi thứ hoàn hảo. Trong lập trình, hầu hết các dự án có thể được biên dịch trong vài giây hoặc vài phút, do đó, không có vấn đề gì nếu không hoàn hảo sớm. Chi phí cho việc suy nghĩ những vấn đề tầm thường trước thời hạn thường lớn hơn chi phí biên dịch lại. Vì vậy, chúng tôi biên dịch lại tất cả các thời gian.

TDD là nguyên tắc tương tự, chỉ cần xoay để kiểm tra đi lên phía trước. Nếu thử nghiệm có thể được thực hiện siêu rẻ (vì vậy tất cả chỉ chạy trong vài giây), thì chi phí suy nghĩ thông qua bức tranh lớn, giải pháp tổng thể, hoàn hảo trong một lần lặp mã hóa lớn hơn nhiều so với chi phí tái cấu trúc.

Ngoại trừ...

Có một số điều trong lập trình mà những đối số này không theo kịp. Đó là mục đích của kiến ​​trúc. Xác định và lên kế hoạch trước những lo ngại sẽ tốn kém hơn để thay đổi sau này. Ví dụ: bạn sẽ không chọn cơ sở dữ liệu một cách nhanh chóng mà không nghĩ về nhu cầu của mình, bắt đầu xây dựng và chỉ cần lập luận rằng bạn có thể thay đổi cơ sở dữ liệu sau. Bạn cần phải suy nghĩ kỹ.


1
Điểm tuyệt vời trong việc xác minh bài kiểm tra! Ngoài ra: khi xây dựng một ngôi nhà, nó CỨNG để di chuyển một bức tường (và điều này để lại sẹo). Với phần mềm, việc di chuyển mã xung quanh tương đối dễ dàng - miễn là bạn có kiểm tra tự động để nắm bắt mọi thay đổi ngoài ý muốn.
Technophile

4

Tôi đã từng tự hỏi về điều này rất nhiều cho đến khi tôi thực hiện một vài dự án của TDD. Có một lời giải thích rất ngắn gọn và toàn diện xuất hiện trong khi tôi làm điều này:

Khi bạn viết mã, bạn phải có một số cách để đảm bảo mã làm điều gì đó có ý nghĩa. Vì vậy, bạn kiểm tra mã của bạn. Bạn có thể làm thử nghiệm ad hoc. Tuy nhiên, kiểm tra hoạt động tốt hơn nếu bạn nghĩ về cách kiểm tra trước khi bạn bắt đầu làm việc. Vì vậy, bạn thiết kế chiến lược thử nghiệm trước khi bạn đi thử nghiệm.

Bây giờ vì bạn đang nghĩ về chiến lược thử nghiệm của mình, bạn cũng có thể tự động hóa, ít nhất là một phần của nó ... Và hãy xem bạn có một số mức độ TDD. Việc bạn viết mã cho đến khi bạn vượt qua bài kiểm tra là điều bình thường. Đó là những gì bạn làm dù sao, viết mã cho đến khi nó hoạt động. Bây giờ thật dễ dàng để làm nổ tung các bài kiểm tra.

Vì những lý do ngoài phạm vi, bạn không viết toàn bộ nội dung trong một lần. Vì vậy, bạn không thiết kế các bài kiểm tra trong một lần. Nhưng về cơ bản đó là những gì nó được. Chỉ cần lập kế hoạch kiểm tra tốt hơn, bạn không phải lúc nào cũng viết kiểm tra lên phía trước. Đôi khi bạn thêm nhiều hơn khi bạn tiến bộ và tìm thấy các lỗi bạn không lường trước được hoặc làm cho bài kiểm tra mạnh mẽ hơn sau này. Và đôi khi bạn có thể thấy mình không thiết kế các bài kiểm tra, nhưng hãy tìm thử nghiệm thủ công để bạn thực hiện các bài kiểm tra sau.

Vì vậy, TDD chỉ là một cách cực đoan trong việc xem xét cách bạn xác nhận công việc của bạn.


4

Mặc dù câu hỏi này đã có câu trả lời được chấp nhận, tôi tin rằng tôi có một cái gì đó để thêm vào, đến từ phong cách thiết kế thử nghiệm không có văn bản (tất cả các thử nghiệm được thực hiện thủ công bởi "người thử nghiệm" theo quy trình thử nghiệm) cho TDD. Đây chỉ là những quan sát cá nhân của tôi, mặc dù tôi tin rằng chúng khá phổ biến.

Khi bạn viết một cái gì đó mới, điều gì đó bạn chưa từng làm trước đây, không có sự khác biệt đáng kể giữa TDD và không làm TDD.

Nói chung, những gì bạn làm là viết một đoạn mã nhỏ để khám phá một ý tưởng, sau đó thêm một số bit được mã hóa cứng để "thử nghiệm", sau đó biên dịch và / hoặc thực hiện nó. Nếu nó hoạt động, bạn sẽ xóa nội dung được mã hóa cứng và tổng quát hóa mã bằng cách thêm tham số, biến thể hiện, v.v.

Hãy suy nghĩ về nó. Đó chính xác là cùng một lượng công việc như TDD. Sự khác biệt duy nhất là ở TDD, bạn viết các bit "thử nghiệm" riêng biệt trong một tệp khác và không xóa chúng ở cuối. Trong TDD bạn giữ mã kiểm tra của bạn .

Tất nhiên, TDD có tổ chức hơn một chút có nghĩa là có thêm một chút công việc tìm ra cách tách các bit kiểm tra mã khỏi mã thực của bạn. Nhưng nếu bạn đã viết bài kiểm tra đơn vị trước khi bạn học cách mô đun hóa mã của mình để kiểm tra.


2

Tại sao nhanh nhẹn tất cả về phát triển dựa trên thử nghiệm (TDD) và không phải thử nghiệm theo hướng phát triển (DDT)?

Chỉ cần ríu rít ở đây vì tôi thấy rằng câu hỏi cho thấy một sự thật ("nhanh nhẹn là tất cả về TDD") mà tôi thấy khá khó chịu. Tất cả các câu trả lời dường như có thực tế này như được cấp. Chúng là những câu trả lời tốt nếu bạn cho rằng nhanh nhẹn chủ yếu là về TDD (hay còn gọi là thử nghiệm ở cấp độ đơn vị).

https://en.wikipedia.org/wiki/Agile_software_development#Agile_methods liệt kê một tá tốt hoặc nhiều mô hình phát triển khác nhau.

Tôi đặc biệt cung cấp Phát triển hướng hành vi và Phát triển dựa trên tính năng như là thực phẩm để suy nghĩ. Những con thú hoàn toàn khác nhau cũng có thể dẫn đến tất cả những lợi ích của TDD cơ bản nhưng khác xa với chu kỳ tái cấu trúc màu đỏ-xanh lá cây đơn giản.

Vì vậy, câu trả lời của tôi ist:

  • "DDT" (hay còn gọi là kiểm tra viết sau hoặc "trên đỉnh" của việc triển khai) không hoạt động vì lý do thực tế; ngay khi bạn gặp áp lực về thời gian hoặc tiền bạc, các bài kiểm tra sẽ ra khỏi cửa sổ; và chỉ có các bài kiểm tra vì lợi ích của việc kiểm tra là đúng hơn, IMO.
  • Agile không phải là tất cả về phát triển dựa trên thử nghiệm (TDD) nếu bạn diễn giải thuật ngữ đó về cơ bản có nghĩa là "kiểm thử đơn vị cho tất cả các khối / lớp xây dựng" (ít nhất là theo Wikipedia, là trường hợp). TDD chỉ là một khả năng để phát triển nhanh.
  • Có các phương pháp khác, như BDD hoặc FDD, thực hiện cách tiếp cận toàn ngăn xếp. Bạn vẫn viết kịch bản của mình lên phía trước, bạn vẫn có chu trình tái cấu trúc màu đỏ-xanh và bạn vẫn chỉ thực hiện cho đến khi kịch bản của bạn có màu xanh, nhưng "kiểm tra" của bạn theo định nghĩa sẽ loại bỏ toàn bộ phần mềm (bằng cách hoạt động như tương tác của người dùng) và không bao giờ chỉ có một đơn vị duy nhất.

Tôi muốn có một ứng dụng có phạm vi bảo hiểm BDD / FDD hoàn chỉnh và không có thử nghiệm đơn vị nào hơn một ứng dụng có phạm vi kiểm tra đơn vị hoàn chỉnh và không có thử nghiệm toàn ngăn xếp.

(TDD có vị trí của khóa học, ví dụ như trong API, nhưng đó không phải là những gì chúng ta đang nói ở đây.)

Một lần nữa, tôi không cố gắng từ chối tất cả các câu trả lời khác ở đây, chỉ nêu ra rằng câu hỏi được đặt ra khá hẹp và lĩnh vực này có nhiều hơn để cung cấp.


Tôi biết về người khác nhưng tại thời điểm viết bài này, ddt dường như có ý nghĩa hơn. Quan tâm để giải thích tại sao TDD tốt hơn cho API? Làm thế nào để sử dụng nó trên nói một máy khách web với MVC khác nhau?
mọt sách

1
Trong các API, điều cực kỳ quan trọng là chúng phải tuân theo một hợp đồng rất chi tiết ; mỗi cuộc gọi phương thức phải hành xử rất dễ đoán đối với người dùng (là các chương trình khác) để sử dụng chính xác. Đây là nơi thử nghiệm đơn vị thực sự tỏa sáng. OTOH, trong một ứng dụng, điều quan trọng nhất đối với các tính năng mà con người của bạn cần để hoạt động như dự định. Chắc chắn, "nội bộ" của bạn cũng tốt hơn, nhưng điều quan trọng hơn là phải có phạm vi bảo hiểm tốt về chức năng "kết thúc để kết thúc" (nghĩa là từ UI ngay vào DB và trở lại) thay vì kiểm tra từng phương thức riêng lẻ (mà người dùng cuối sẽ không nhìn thấy dù sao).
AnoE

Tất nhiên, tất cả đều ở các mức độ khác nhau ở đây - có thể có ý nghĩa khi phân tích các bài kiểm tra đơn vị ở đây cũng như nếu bạn nên có các phương thức / lớp rất phức tạp ở đâu đó (ví dụ: tính khoảng cách giữa các geocoord); nhưng phần lớn (ví dụ, trong các ứng dụng kinh doanh) là quy trình công việc tổng thể.
AnoE

0

Mặc dù bạn không thấy nó được viết theo cách này thường xuyên, nhưng phần lớn lý do đằng sau sự nhanh nhẹn là viết lại mã tốt hơn so với viết lần đầu tiên. Mỗi khi bạn viết lại mã, bạn sẽ cải thiện mã và cải thiện bản thân. Làm cho nó "Đúng" lần đầu tiên có xu hướng chậm hơn và dễ gãy hơn.

Sự tương tự ngôi nhà không tệ lắm, nhưng bạn phải suy nghĩ về việc chúng ta đã biết về xây dựng nhà trong bao lâu so với thời gian chúng ta biết về công nghệ phần mềm - cũng là sự phức tạp của công nghệ phần mềm gần với việc xây dựng một cây cầu dài hoặc tháp 20 tầng hơn một ngôi nhà. Chúng ta cũng nên xem xét rằng với các ngôn ngữ và công cụ mới được xây dựng, giống như mọi nhà xây dựng muốn xây dựng tòa nhà với hình dạng, kích thước và vật liệu hoàn toàn khác nhau. Sự hỗn loạn hoàn toàn.

Tuy nhiên, kiểm tra không phải là một sự tương tự tốt để kiểm tra mã. Trong phần mềm, chúng tôi thậm chí không đến mức chúng tôi CÓ người kiểm tra đàng hoàng (Ngoại trừ các đồng nghiệp của bạn ở các cấp độ kỹ năng khác nhau). Chúng tôi cũng không có quy định để kiểm tra ngoại trừ, có lẽ, một số "tiêu chuẩn mã hóa" chủ yếu là tùy tiện (giống như kiểm tra màu sơn và bố cục bãi cỏ của bạn hơn là cấu trúc).

Thử nghiệm đầu tiên giống như bạn xây dựng một bức tường sau đó bạn áp dụng một số áp lực lên nó để đảm bảo sự ổn định trước khi nâng nó và đặt nó lên ngôi nhà của bạn. Nó giống như đo cửa sổ để đảm bảo nó sẽ vừa với lỗ bạn để lại trước khi thử đặt nó.

Nếu bạn phải xây dựng một loạt các cây cầu mà không có kiến ​​thức, mô hình, quy định và toán học kiến ​​trúc trước đây mà chúng tôi phải chứng minh các cây cầu của chúng tôi sẽ hoạt động trước khi chúng tôi xây dựng chúng, có lẽ bạn đang thử nghiệm và xây dựng lại cây cầu của mình RẤT NHIỀU.

Cuối cùng, một điểm không tương tự - với phần mềm mỗi khi bạn được phép viết lại một phần mã của mình, bạn sẽ cải thiện cả mã và kỹ năng của mình một cách đáng kể. Tận dụng mọi cơ hội bạn có thể để viết lại mã. TDD có thể là một cái cớ tuyệt vời.

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.