Làm thế nào em bé là bước của em bé trong TDD?


37

Hôm nay chúng tôi đã đào tạo TDD và tìm thấy điểm hiểu lầm sau đây.

Nhiệm vụ dành cho tổng số trả về "1,2" đầu vào là 3. Những gì tôi đã viết (bằng C #) là:

numbers = input.Split(',');
return int.Parse(numbers[0]) + int.Parse(numbers[1]); //task said we have two numbers and input is correct

Nhưng những người khác thích làm theo cách khác. Đầu tiên, đối với đầu vào "1,2", họ đã thêm mã sau đây:

if (input == "1,2")
   return 3;

Sau đó, họ giới thiệu thêm một bài kiểm tra cho đầu vào "4,5" và thay đổi triển khai:

if (input == "1,2")
   return 3;
else if (input == "4,5")
   return 9;

Và sau đó họ nói "Được rồi, bây giờ chúng ta thấy mô hình" và thực hiện những gì tôi đã làm ban đầu.

Tôi nghĩ rằng cách tiếp cận thứ hai phù hợp hơn với định nghĩa TDD nhưng ... chúng ta có nên nghiêm ngặt về nó không? Đối với tôi, có thể bỏ qua các bước bé tầm thường và kết hợp chúng thành "hai bước" nếu tôi chắc chắn rằng tôi sẽ không bỏ qua bất cứ điều gì. Tôi có lầm không?

Cập nhật. Tôi đã phạm sai lầm khi không làm rõ nó không phải là thử nghiệm đầu tiên. Đã có một số thử nghiệm vì vậy "return 3" thực sự không phải là đoạn mã đơn giản nhất để đáp ứng yêu cầu.


25
Nhỏ đến nỗi đồng nghiệp của tôi phải thốt lên "Ooahhh dazso cuuuuuute"
Adel

6
@Adel: Gần như bị nghẹn trong bữa sáng của tôi, bàn phím giờ đã đầy hoặc dễ vỡ và vụn
Binary Worrier

2
@Adel, đối với người không phải người bản ngữ, tôi khá khó hiểu được sự hài hước này nhưng tôi đoán đồng nghiệp của bạn thích câu hỏi :)
SiberianGuy

8
@Idsa: Đó là chuyển đổi câu trả lời của đồng nghiệp khi cho trẻ em thấy những bước đầu tiên "Ooahhh dazso cuuuuuute" = "Ôi thật dễ thương" (nói bằng giọng hát không phải là rất dễ thương) khi nhìn thấy Bài kiểm tra đơn vị được viết bởi Adel, nhìn vào các bước của Bài kiểm tra đơn vị, họ nói "Ôi thật dễ thương". Phản ứng với các bước thực - trẻ sơ sinh = phản ứng với đơn vị kiểm tra "các bước bé".
Nhị phân nhị phân

3
@Binaryworrier ước tôi có thể cho bạn những điểm thực sự để dành thời gian giải thích cho phụ huynh
Andrew T Finnell

Câu trả lời:


31

Viết mã đơn giản nhất làm cho các bài kiểm tra vượt qua.

Không ai trong số các bạn đã làm điều đó, theo như tôi có thể thấy.

Bước 1.

Kiểm tra: Đối với tổng trả về "1,2" của các số là 3

Làm bài kiểm tra thất bại:

throw NotImplementedException();

Làm bài kiểm tra vượt qua:

return 3;

Bước 2 cho bé.

Kiểm tra: Đối với tổng số trả về "1,2" đầu vào là 3

Kiểm tra: Đối với tổng số trả về "4,5" đầu vào, là 9

Thử nghiệm thứ hai không thành công, vì vậy hãy vượt qua:

numbers = input.Split(',');
return int.Parse(numbers[0]) + int.Parse(numbers[1]);

(Cách đơn giản hơn danh sách nếu ... trở về)

Bạn chắc chắn có thể tranh luận Thực hiện rõ ràng trong trường hợp này, nhưng nếu bạn đang nói về việc thực hiện nghiêm túc trong các bước bé thì đây là những bước chính xác, IMO.

Lập luận là nếu bạn không viết bài kiểm tra thứ hai thì một số tia sáng rực rỡ có thể xuất hiện sau đó và "tái cấu trúc" mã của bạn để đọc:

return input.Length; # Still satisfies the first test

Và, không thực hiện cả hai bước, bạn chưa bao giờ làm cho bài kiểm tra thứ hai chuyển sang màu đỏ (có nghĩa là bản thân bài kiểm tra bị nghi ngờ).


Về đầu vào của bạn. Ví dụ về độ dài, với cùng một thành công, tôi có thể tưởng tượng một số triển khai không chính xác điên rồ sẽ không bị bắt bởi cả hai thử nghiệm
SiberianGuy

@Idsa - Vâng, hoàn toàn, và bạn càng viết nhiều bài kiểm tra, việc thực hiện càng điên rồ. input.Lengthkhông phải là quá xa vời, đặc biệt là nếu đầu vào của phương thức xảy ra là một phép đo từ một số tệp ở đâu đó và bạn vô tình gọi phương thức của mình Size().
Lào

6
+1. Đối với cách học TDD, đây là cách đúng đắn. Một khi bạn đã học nó, đôi khi bạn có thể trực tiếp đến việc triển khai rõ ràng, nhưng để cảm nhận về TDD, điều này tốt hơn nhiều.
Carl Manaster

1
Tôi có một câu hỏi liên quan đến "thử nghiệm" chính nó. Bạn sẽ viết một bài kiểm tra mới cho đầu vào "4,5" hoặc sửa đổi bài kiểm tra gốc?
mxmissile

1
@mxmissile: Tôi sẽ viết một bài kiểm tra mới. Sẽ không mất nhiều thời gian và bạn kết thúc với gấp đôi số lần kiểm tra để bảo vệ bạn khi bạn thực hiện tái cấu trúc sau đó.
pdr

50

Tôi nghĩ rằng cách thứ hai là tâm trí ngu ngốc. Tôi thấy giá trị của việc thực hiện các bước đủ nhỏ, nhưng viết các hợp tử nhỏ bé đó (thậm chí không thể gọi chúng là các bước) chỉ là asinine và lãng phí thời gian. Đặc biệt là nếu vấn đề ban đầu bạn giải quyết đã rất nhỏ.

Tôi biết đó là đào tạo và nó thể hiện nhiều hơn về nguyên tắc, nhưng tôi nghĩ những ví dụ như vậy làm TDD tệ hơn là tốt. Nếu bạn muốn hiển thị giá trị của các bước bé, ít nhất hãy sử dụng một vấn đề trong đó có một số giá trị trong đó.


+1 và cảm ơn vì đã khiến tôi tìm kiếm và học một từ mới (asinine)
Marjan Venema

12
+1 để gọi nó là ngu ngốc. TDD là tất cả tốt đẹp và như vậy, nhưng giống như với bất kỳ kỹ thuật lập trình thổi phồng hiện đại nào, bạn nên cẩn thận để không bị lạc vào nó.
stijn

2
"Đặc biệt là nếu vấn đề ban đầu mà bạn giải quyết đã rất nhỏ. - Nếu đầu vào là hai int được thêm vào với nhau, tôi sẽ đồng ý với điều này, nhưng tôi không bị thuyết phục khi nó "tách một chuỗi, phân tích hai int từ kết quả và thêm chúng." Hầu hết các phương pháp trong thế giới thực không phức tạp hơn thế nhiều. Trên thực tế, cần có thêm các thử nghiệm sắp tới, để bao quát các trường hợp cạnh như tìm hai dấu phẩy, giá trị không nguyên, v.v.
pdr

4
@pdr: Tôi đồng ý với bạn rằng cần có thêm các bài kiểm tra để xử lý các trường hợp cạnh. Khi bạn viết chúng và nhận thấy rằng việc triển khai của bạn cần thay đổi để xử lý chúng, bằng mọi cách hãy làm điều đó. Tôi đoán rằng tôi chỉ gặp vấn đề với việc thực hiện các bước hợp tử đến con đường hạnh phúc đầu tiên, "triển khai rõ ràng", thay vì chỉ viết nó xuống và đi từ đó. Tôi không thấy giá trị khi viết ra một tuyên bố if mà mọi chất xơ trong cơ thể tôi biết sẽ biến mất vào khoảnh khắc tiếp theo.
Barshe Vanfleteren

1
@ChristopheVanfleteren: Khi Beck mô tả việc triển khai rõ ràng, anh ta sử dụng tổng của hai số nguyên làm ví dụ và vẫn đưa ra một cảnh báo kịch tính lớn về việc bạn sẽ chết vì xấu hổ như thế nào nếu cặp / người đánh giá của bạn có thể nghĩ về mã đơn giản hơn làm cho vượt qua kiểm tra. Đó là một sự chắc chắn tuyệt đối nếu bạn chỉ viết một bài kiểm tra cho kịch bản này. Ngoài ra, tôi có thể nghĩ ra ít nhất ba cách "rõ ràng" để giải quyết vấn đề này: chia & thêm, thay thế dấu phẩy bằng + và đánh giá hoặc sử dụng regex. Quan điểm của TDD là đưa bạn đến sự lựa chọn chính xác.
pdr

19

Kent Beck trình bày điều này trong cuốn sách của mình, Test Driven Development: Ví dụ.

Ví dụ của bạn cho thấy một ' triển khai rõ ràng ' - bạn muốn trả về tổng hai giá trị đầu vào và đây là một thuật toán khá cơ bản để đạt được. Ví dụ phản biện của bạn rơi vào 'giả mạo cho đến khi bạn thực hiện nó' (mặc dù trường hợp rất đơn giản).

Việc triển khai rõ ràng có thể phức tạp hơn nhiều so với điều này - nhưng về cơ bản, nó khởi động khi đặc tả cho một phương thức khá chặt chẽ - ví dụ, trả về một phiên bản được mã hóa URL của một thuộc tính lớp - bạn không cần lãng phí thời gian với một loạt mã hóa giả mạo.

Mặt khác, một thói quen kết nối cơ sở dữ liệu sẽ cần suy nghĩ và thử nghiệm nhiều hơn một chút để không có triển khai rõ ràng (ngay cả khi bạn có thể đã viết một vài lần cho các dự án khác).

Từ cuốn sách:

Khi tôi sử dụng TDD trong thực tế, tôi thường chuyển đổi giữa hai chế độ triển khai này, Khi mọi thứ diễn ra suôn sẻ và tôi biết nên gõ gì, tôi đưa vào Thực hiện rõ ràng sau khi thực hiện rõ ràng (chạy thử nghiệm mỗi lần để đảm bảo rằng điều đó rõ ràng với tôi vẫn còn rõ ràng với máy tính). Ngay khi tôi nhận được một thanh màu đỏ bất ngờ, tôi sao lưu, chuyển sang thực hiện giả mạo và cấu trúc lại mã đúng. Khi sự tự tin của tôi trở lại, tôi quay trở lại Triển khai Rõ ràng.


18

Tôi thấy điều này như sau lá thư của pháp luật, nhưng không phải tinh thần của nó.

Các bước cho bé của bạn nên là:

Càng đơn giản càng tốt, nhưng không đơn giản hơn.

Ngoài ra, động từ trong phương thức là sum

if (input == "1,2")
   return 3;

không phải là một khoản tiền, đó là một thử nghiệm cho các đầu vào cụ thể.


4

Đối với tôi có vẻ tốt khi kết hợp một số bước thực hiện tầm thường thành một ít tầm thường hơn - tôi cũng làm điều đó mọi lúc. Tôi không nghĩ người ta cần phải tôn giáo về việc theo dõi TDD mỗi lần gửi thư.

OTOH điều này chỉ áp dụng cho các bước thực sự tầm thường như ví dụ trên. Đối với bất cứ điều gì phức tạp hơn, mà tôi không thể hoàn toàn giữ trong tâm trí của mình cùng một lúc và / hoặc nơi tôi không chắc chắn 110% về kết quả, tôi thích đi từng bước một.


1

Khi lần đầu tiên đặt ra con đường của TDD, kích thước của các bước có thể là một vấn đề khó hiểu, như câu hỏi này minh họa. Một câu hỏi tôi thường tự hỏi khi lần đầu tiên bắt đầu viết các ứng dụng điều khiển thử nghiệm là; Là bài kiểm tra tôi đang viết giúp thúc đẩy sự phát triển ứng dụng của tôi? Điều này có vẻ tầm thường và không liên quan đến một số người nhưng hãy ở đó với tôi một lát.

Bây giờ khi tôi bắt đầu viết bất kỳ ứng dụng nào, tôi thường sẽ bắt đầu bằng một bài kiểm tra. Bao nhiêu bước mà bài kiểm tra phần lớn liên quan đến sự hiểu biết của tôi về những gì tôi đang cố gắng làm. Nếu tôi nghĩ rằng tôi có khá nhiều hành vi của một lớp học trong đầu thì bước đó sẽ là một bước lớn. Nếu vấn đề tôi đang cố gắng giải quyết ít rõ ràng hơn thì bước có thể đơn giản là tôi biết sẽ có một phương thức có tên X và nó sẽ trả về Y. Lúc này phương thức thậm chí không có bất kỳ tham số nào và có khả năng tên của phương thức và kiểu trả về sẽ thay đổi. Trong cả hai trường hợp, các bài kiểm tra đang thúc đẩy sự phát triển của tôi. Họ đang nói với tôi những điều về ứng dụng của tôi:

Đây có phải là lớp học mà tôi có trong đầu thực sự sẽ đi làm?

hoặc là

Làm thế quái nào tôi thậm chí sẽ làm điều này?

Vấn đề là tôi có thể chuyển đổi giữa các bước lớn và bước nhỏ trong chớp mắt. Ví dụ: nếu một bước lớn không hoạt động và tôi không thể thấy một cách rõ ràng xung quanh nó, tôi sẽ chuyển sang một bước nhỏ hơn. Nếu nó không hoạt động tôi sẽ chuyển sang một bước thậm chí nhỏ hơn. Sau đó, có các kỹ thuật khác như triangulation nếu tôi thực sự bị mắc kẹt.

Nếu như tôi, bạn là một nhà phát triển và không phải là người thử nghiệm thì quan điểm của việc sử dụng TDD không phải là viết bài kiểm tra mà là viết mã. Đừng gác máy khi viết vô số bài kiểm tra nhỏ nếu chúng không mang lại cho bạn bất kỳ lợi ích nào.

Tôi hy vọng bạn thích tập luyện của mình với TDD. IMHO nếu nhiều người được kiểm tra bị nhiễm thì thế giới sẽ là một nơi tốt hơn :)


1

Trong phần sơ khai về kiểm tra đơn vị, tôi đã đọc cách tiếp cận tương tự (các bước trông thực sự rất nhỏ) và như một câu trả lời cho câu hỏi "chúng nên nhỏ như thế nào", một thứ tôi thích, được diễn giải như thế này:

Đó là về mức độ tự tin của bạn rằng các bước làm việc. Bạn có thể thực hiện các bước lớn thực sự nếu bạn muốn. Nhưng, chỉ cần thử một thời gian và bạn sẽ thấy rất nhiều sự tự tin sai lầm ở những nơi bạn coi đó là điều hiển nhiên. Vì vậy, các bài kiểm tra giúp bạn xây dựng sự tự tin dựa trên thực tế.

Vì vậy, có lẽ đồng nghiệp của bạn chỉ là một chút ngại ngùng :)


1

Không phải toàn bộ vấn đề là việc thực hiện phương pháp là không liên quan, miễn là các thử nghiệm thành công? Mở rộng các bài kiểm tra sẽ thất bại nhanh hơn trong ví dụ thứ hai, nhưng có thể được thực hiện để thất bại trong cả hai trường hợp.


1
Sẽ không liên quan nếu bạn hoàn toàn không quan tâm đến việc lãng phí thời gian của mình
SiberianGuy

1

Tôi đồng ý với những người nói rằng đó không phải là cách thực hiện đơn giản nhất.

Lý do phương pháp rất nghiêm ngặt là vì nó bắt buộc bạn phải viết càng nhiều bài kiểm tra có liên quan càng tốt. Trả về một giá trị không đổi cho một trường hợp thử nghiệm và gọi nó là vượt qua là tốt vì nó buộc bạn phải quay lại và chỉ định những gì bạn thực sự muốn để có được bất cứ điều gì khác ngoài vô nghĩa từ chương trình của bạn. Sử dụng một trường hợp tầm thường như vậy là tự bắn vào chân mình ở một số khía cạnh, nhưng nguyên tắc là những sai lầm len lỏi vào các lỗ hổng trong đặc tả của bạn khi bạn cố gắng thực hiện 'quá nhiều' và đưa ra yêu cầu để thực hiện đơn giản nhất có thể đảm bảo rằng kiểm tra phải được viết cho từng khía cạnh duy nhất của hành vi mà bạn thực sự muốn.


Tôi đã thêm một bản cập nhật liên quan đến "trả lại giá trị không đổi"
SiberianGuy
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.