Các bài kiểm tra đơn vị có giúp Citigroup tránh được sai lầm đắt giá này không?


86

Tôi đã đọc về snafu này: Lỗi lập trình gây thiệt hại cho Citigroup 7 triệu đô la sau khi các giao dịch hợp pháp bị nhầm lẫn với dữ liệu thử nghiệm trong 15 năm .

Khi hệ thống được giới thiệu vào giữa những năm 1990, mã chương trình đã lọc ra bất kỳ giao dịch nào được cung cấp mã nhánh ba chữ số từ 089 đến 100 và sử dụng các tiền tố đó cho mục đích thử nghiệm.

Nhưng vào năm 1998, công ty bắt đầu sử dụng mã chi nhánh chữ và số khi mở rộng kinh doanh. Trong số đó có các mã 10B, 10C, v.v., hệ thống được coi là nằm trong phạm vi bị loại trừ, và vì vậy các giao dịch của họ đã bị xóa khỏi mọi báo cáo gửi đến SEC.

(Tôi nghĩ rằng điều này minh họa rằng việc sử dụng một chỉ báo dữ liệu không rõ ràng là ... tối ưu phụ. Sẽ tốt hơn nhiều khi cư trú và sử dụng một thuộc Branch.IsLivetính rõ ràng về ngữ nghĩa .)

Bỏ qua một bên, phản ứng đầu tiên của tôi là "Các bài kiểm tra đơn vị sẽ có ích ở đây" ... nhưng liệu họ có làm được không?

Gần đây tôi đã đọc Tại sao hầu hết các thử nghiệm đơn vị là lãng phí với sự quan tâm, và vì vậy câu hỏi của tôi là: các thử nghiệm đơn vị sẽ thất bại khi giới thiệu mã ngành chữ và số trông như thế nào?



17
Có vẻ như họ cũng đã bỏ lỡ một bài kiểm tra tích hợp kiểm tra số lượng giao dịch được xuất sang SEC. Nếu bạn xây dựng một tính năng xuất sẽ là một kiểm tra hợp lý.
Luc Franken

31
Tác giả của bài viết dường như không hiểu thử nghiệm đơn vị. Một số tuyên bố chỉ là vô lý ( "các bài kiểm tra đơn vị không thể kiểm tra nhiều hơn một phần nghìn tỷ chức năng của bất kỳ phương pháp nào" ), những bài kiểm tra khác sẽ phá hủy cơ hội nhận hồi quy ( "nhìn vào các bài kiểm tra chưa bao giờ thất bại trong một năm và xem xét việc ném chúng đi " ). Hoặc các đề xuất như "biến các bài kiểm tra đơn vị thành các xác nhận" , được cho là thay đổi các bài kiểm tra thất bại cho các ngoại lệ thời gian chạy?
Groo

25
@gnat Tôi không đọc liên kết bên ngoài và tôi vẫn thấy câu hỏi này có ý nghĩa
Jeutnarg

23
Đối với những gì nó có giá trị, tôi khá không đồng ý với mọi thứ trong "Tại sao hầu hết các thử nghiệm đơn vị là lãng phí." Tôi sẽ viết một phản bác, nhưng lề này quá nhỏ để chứa nó.
Robert Harvey

Câu trả lời:


19

Bạn có thực sự hỏi, "các bài kiểm tra đơn vị có giúp được gì ở đây không?", Hoặc bạn đang hỏi, "có thể có bất kỳ loại bài kiểm tra nào có thể giúp được ở đây không?".

Hình thức kiểm tra rõ ràng nhất sẽ có ích, là một xác nhận tiền điều kiện trong chính mã, rằng một định danh nhánh chỉ bao gồm các chữ số (giả sử rằng đây là giả định được dựa trên mã hóa khi viết mã).

Điều này sau đó có thể đã thất bại trong một số loại thử nghiệm tích hợp và ngay khi các id nhánh alpha-số mới được giới thiệu thì xác nhận sẽ nổ tung. Nhưng đó không phải là một bài kiểm tra đơn vị.

Ngoài ra, có thể có một thử nghiệm tích hợp của quy trình tạo báo cáo SEC. Thử nghiệm này đảm bảo rằng mọi mã định danh chi nhánh thực báo cáo các giao dịch của nó (và do đó yêu cầu đầu vào trong thế giới thực, danh sách tất cả các mã định danh chi nhánh đang sử dụng). Vì vậy, đó không phải là một bài kiểm tra đơn vị.

Tôi không thể thấy bất kỳ định nghĩa hoặc tài liệu nào về các giao diện liên quan, nhưng có thể các thử nghiệm đơn vị có thể đã phát hiện ra lỗi vì thiết bị không bị lỗi . Nếu đơn vị được phép giả định rằng số nhận dạng chi nhánh chỉ bao gồm các chữ số và các nhà phát triển không bao giờ đưa ra quyết định mã nên làm gì trong trường hợp không, thì họ không nênviết một bài kiểm tra đơn vị để thực thi hành vi cụ thể trong trường hợp số nhận dạng không có chữ số vì bài kiểm tra sẽ từ chối việc triển khai hợp lệ giả định của đơn vị đã xử lý chính xác số nhận dạng nhánh chữ và số, bạn thường không muốn viết bài kiểm tra đơn vị ngăn chặn hợp lệ triển khai và mở rộng trong tương lai. Hoặc có thể một tài liệu được viết cách đây 40 năm đã được định nghĩa ngầm (thông qua một số phạm vi từ vựng trong EBCDIC thô, thay vì quy tắc đối chiếu thân thiện với con người hơn) rằng 10B là một định danh kiểm tra vì thực tế nó nằm trong khoảng từ 089 đến 100. Nhưng sau đó 15 năm trước, một người nào đó đã quyết định sử dụng nó như một định danh thực sự, vì vậy "lỗi" không nằm trong đơn vị thực hiện chính xác định nghĩa ban đầu: nó nằm trong quy trình không nhận thấy rằng 10B được xác định là định danh kiểm tra và do đó không nên gán cho một chi nhánh. Điều tương tự sẽ xảy ra trong ASCII nếu bạn xác định 089 - 100 làm phạm vi thử nghiệm và sau đó giới thiệu mã định danh 10 $ hoặc 1.0. Nó chỉ xảy ra rằng trong EBCDIC các chữ số đến sau các chữ cái.

Một thử nghiệm đơn vị (hoặc được cho là thử nghiệm chức năng) có thể hiểu đượccó thể đã lưu trong ngày, là một thử nghiệm của đơn vị tạo hoặc xác nhận định danh chi nhánh mới. Thử nghiệm đó sẽ khẳng định rằng các định danh phải chỉ chứa các chữ số và sẽ được viết để cho phép người dùng của các định danh chi nhánh giả định giống nhau. Hoặc có lẽ có một đơn vị ở đâu đó nhập số nhận dạng chi nhánh thực nhưng không bao giờ thấy bộ kiểm tra và có thể được kiểm tra đơn vị để đảm bảo đơn vị đó từ chối tất cả số nhận dạng kiểm tra (nếu số nhận dạng chỉ có ba ký tự chúng ta có thể liệt kê tất cả và so sánh hành vi của trình xác nhận hợp lệ của bộ lọc thử nghiệm để đảm bảo chúng khớp với nhau, liên quan đến sự phản đối thông thường đối với các thử nghiệm tại chỗ). Sau đó, khi ai đó thay đổi các quy tắc, bài kiểm tra đơn vị sẽ thất bại vì nó mâu thuẫn với hành vi mới được yêu cầu.

Vì thử nghiệm là có lý do chính đáng, điểm mà bạn cần loại bỏ do yêu cầu kinh doanh thay đổi sẽ trở thành cơ hội để ai đó được giao việc, "tìm mọi vị trí trong mã dựa trên hành vi mà chúng tôi muốn thay đổi". Tất nhiên điều này là khó khăn và do đó không đáng tin cậy, do đó sẽ không có nghĩa là đảm bảo tiết kiệm trong ngày. Nhưng nếu bạn nắm bắt được các giả định của mình trong các thử nghiệm của các đơn vị mà bạn giả định thuộc tính, thì bạn đã cho mình một cơ hội và vì vậy nỗ lực này không hoàn toàn lãng phí.

Tất nhiên tôi đồng ý rằng nếu đơn vị chưa được xác định ở vị trí đầu tiên với đầu vào "hình ngộ nghĩnh" thì sẽ không có gì để kiểm tra. Sự phân chia không gian tên khó khăn có thể khó kiểm tra đúng bởi vì khó khăn không nằm ở việc thực hiện định nghĩa hài hước của bạn, nó nằm ở việc đảm bảo rằng mọi người đều hiểu và tôn trọng định nghĩa hài hước của bạn. Đó không phải là một tài sản cục bộ của một đơn vị mã. Hơn nữa, việc thay đổi một số loại dữ liệu từ "một chuỗi chữ số" thành "một chuỗi chữ số" giống như làm cho một chương trình dựa trên ASCII xử lý Unicode: sẽ không đơn giản nếu mã của bạn được kết hợp nhiều với định nghĩa ban đầu và khi nào kiểu dữ liệu là nền tảng cho những gì chương trình thực hiện sau đó nó thường được kết hợp chặt chẽ.

thật đáng lo ngại khi nghĩ rằng nó đã lãng phí công sức

Nếu kiểm tra đơn vị của bạn đôi khi không thành công (ví dụ như trong khi bạn tái cấu trúc) và khi làm như vậy sẽ cung cấp cho bạn thông tin hữu ích (ví dụ: thay đổi của bạn là sai), thì nỗ lực đó đã bị lãng phí. Những gì họ không làm, là kiểm tra xem hệ thống của bạn có hoạt động không. Vì vậy, nếu bạn đang viết bài kiểm tra đơn vị thay vì có bài kiểm tra chức năng và tích hợp thì bạn có thể sử dụng thời gian của mình một cách tối ưu.


Khẳng định là tốt!

3
@nocomprende: như Reagan đã có, "tin tưởng, nhưng xác minh".
Steve Jessop

1
Tôi cũng sẽ nói "Đơn vị kiểm tra xấu!" nhưng tôi nghĩ hầu hết mọi người sẽ bỏ lỡ tài liệu tham khảo đến Animal Farm và thực sự chỉ trích tôi thay vì nghĩ về những gì tôi đang nói (phản ứng giật đầu gối là không hiệu quả) nhưng tôi đã không nói như vậy. Có lẽ một người thông minh hơn và có sự uyên bác lớn hơn có thể đưa ra quan điểm đó.

2
"Tất cả các bài kiểm tra đang qua, nhưng một số bài kiểm tra vượt qua hơn các bài kiểm tra khác!"
Graham

1
thử nghiệm là một cá trích đỏ. Những kẻ này không biết "mã ngành" được định nghĩa như thế nào. Điều này sẽ giống như Bưu điện Hoa Kỳ không biết rằng họ đang thay đổi định nghĩa về mã zip khi thêm 4 chữ số.
radarbob

120

Các thử nghiệm đơn vị có thể đã phát hiện ra rằng các mã chi nhánh 10B và 10C được phân loại không chính xác là "các nhánh thử nghiệm", nhưng tôi thấy rằng các thử nghiệm phân loại chi nhánh đó không đủ rộng để bắt lỗi đó.

Mặt khác, kiểm tra tại chỗ các báo cáo được tạo có thể đã tiết lộ rằng 10B và 10C phân nhánh đã liên tục bị thiếu trong các báo cáo sớm hơn 15 năm mà lỗi hiện đã được phép tồn tại.

Cuối cùng, đây là một minh họa tốt tại sao nên trộn dữ liệu thử nghiệm với dữ liệu sản xuất thực trong một cơ sở dữ liệu. Nếu họ đã sử dụng một cơ sở dữ liệu riêng biệt chứa dữ liệu thử nghiệm, thì sẽ không cần phải lọc ra khỏi các báo cáo chính thức và không thể lọc quá nhiều.


80
+1 Các thử nghiệm đơn vị không bao giờ có thể bù cho các quyết định thiết kế kém (như thử nghiệm trộn và dữ liệu thực)
Jeutnarg

5
Mặc dù tốt nhất là tránh trộn dữ liệu thử nghiệm với dữ liệu thực, nhưng có thể khó xác thực hệ thống sản xuất nếu điều đó yêu cầu sửa đổi dữ liệu thực. Ví dụ: việc xác thực hệ thống ngân hàng bằng cách sửa đổi tổng tài khoản ngân hàng trong sản xuất là một ý tưởng tồi. Sử dụng phạm vi mã để chỉ định ý nghĩa là vấn đề. Một thuộc tính rõ ràng hơn của các hồ sơ có lẽ sẽ là một lựa chọn tốt hơn.
JimmyJames

4
@Voo Tôi nghĩ rằng có một giả định ngầm rằng tồn tại một mức độ phức tạp hoặc yêu cầu về độ tin cậy khi thử nghiệm hệ thống sản xuất thực tế, được triển khai được coi là đáng giá hoặc cần thiết. (Xem xét mức độ có thể sai do biến cấu hình sai.) Tôi có thể thấy đây là trường hợp của một tổ chức tài chính lớn.
jpmc26

4
@Voo Tôi không nói về thử nghiệm. Tôi đang nói về việc xác nhận hệ thống. Trong một hệ thống sản xuất thực tế, có nhiều cách mà nó có thể thất bại mà không liên quan gì đến mã. Nếu bạn đang đưa một hệ thống ngân hàng mới vào sản xuất, bạn có thể gặp một số vấn đề trong db hoặc mạng, v.v. điều đó ngăn cản các giao dịch được áp dụng cho các tài khoản. Tôi chưa bao giờ làm việc tại ngân hàng nhưng tôi khá chắc chắn rằng nó sẽ cau mày khi bắt đầu sửa đổi tài khoản thật bằng các giao dịch giả mạo. Vì vậy, điều đó khiến bạn phải thiết lập tài khoản giả hoặc chờ đợi và cầu nguyện.
JimmyJames

12
@JimmyJames Trong chăm sóc sức khỏe, thường xuyên sao chép cơ sở dữ liệu sản xuất vào môi trường thử nghiệm để thực hiện kiểm tra dữ liệu gần với thực nhất có thể; Tôi nghĩ rằng một ngân hàng có thể làm như vậy.
dj18

75

Các phần mềm đã phải xử lý các quy tắc kinh doanh nhất định. Nếu có các bài kiểm tra đơn vị, các bài kiểm tra đơn vị sẽ kiểm tra xem phần mềm có xử lý chính xác các quy tắc kinh doanh không.

Các quy tắc kinh doanh thay đổi.

Rõ ràng không ai nhận ra rằng các quy tắc kinh doanh đã thay đổi và không ai thay đổi phần mềm để áp dụng các quy tắc kinh doanh mới. Nếu đã có các bài kiểm tra đơn vị, các bài kiểm tra đơn vị đó sẽ phải được thay đổi, nhưng không ai sẽ làm điều đó vì không ai nhận ra rằng các quy tắc kinh doanh đã thay đổi.

Vì vậy, không, bài kiểm tra đơn vị sẽ không bắt được điều đó.

Trường hợp ngoại lệ sẽ là nếu các bài kiểm tra đơn vị và phần mềm đã được tạo bởi các nhóm độc lập và nhóm thực hiện các bài kiểm tra đơn vị đã thay đổi các bài kiểm tra để áp dụng các quy tắc kinh doanh mới. Sau đó, các bài kiểm tra đơn vị sẽ thất bại, hy vọng sẽ dẫn đến sự thay đổi của phần mềm.

Tất nhiên trong trường hợp tương tự nếu chỉ thay đổi phần mềm và không kiểm tra đơn vị, thì kiểm tra đơn vị cũng sẽ thất bại. Bất cứ khi nào kiểm tra đơn vị không thành công, điều đó không có nghĩa là phần mềm bị sai, điều đó có nghĩa là phần mềm hoặc kiểm tra đơn vị (đôi khi cả hai) đều sai.


2
Có khả thi khi có các nhóm khác nhau trong đó một nhóm đang làm việc về mã và nhóm khác trong các bài kiểm tra "đơn vị" không? Làm thế nào mà thậm chí có thể? ... Tôi đang cấu trúc lại mã của mình mọi lúc.
Sergio

2
@Sergio từ một góc độ, tái cấu trúc thay đổi nội bộ trong khi duy trì hành vi - vì vậy nếu bài kiểm tra được viết theo cách kiểm tra hành vi mà không dựa vào nội bộ, thì nó không cần cập nhật.
Daenyth

1
Tôi đã thấy điều này xảy ra một số lần. Phần mềm đang được sản xuất mà không có khiếu nại, sau đó tất cả người dùng bất ngờ bùng nổ với những lời phàn nàn rằng nó không còn hoạt động và đã dần thất bại trong những năm qua. Đó là những gì xảy ra khi bạn quyết định đi và thay đổi quy trình nội bộ của mình mà không tuân theo quy trình thông báo tiêu chuẩn ...
Brian Knoblauch

42
"Các quy tắc kinh doanh thay đổi" là quan sát quan trọng. Kiểm tra đơn vị xác nhận rằng bạn đã triển khai logic mà bạn nghĩ bạn đã triển khai , không phải logic của bạn là chính xác .
Ryan Cavanaugh

5
Nếu tôi đúng về những gì đã xảy ra, không chắc rằng các bài kiểm tra đơn vị để nắm bắt điều này sẽ được viết. Nguyên tắc cơ bản để chọn các bài kiểm tra là kiểm tra một số trường hợp "tốt", một số trường hợp "xấu" và các trường hợp đóng khung bất kỳ ranh giới nào. Trong trường hợp này, bạn sẽ kiểm tra "099", "100" và "101". Vì "10B" được bao phủ bởi các thử nghiệm "từ chối không số" trong hệ thống cũ và lớn hơn 101 (và do đó được bao phủ bởi thử nghiệm đó) trong hệ thống mới, không có lý do nào để kiểm tra nó - ngoại trừ trong EBCDIC, "10B" sắp xếp giữa "099" và "100".
Đánh dấu

29

Không. Đây là một trong những vấn đề lớn với thử nghiệm đơn vị: chúng đưa bạn vào một cảm giác an toàn sai lầm.

Nếu tất cả các bài kiểm tra của bạn vượt qua, điều đó không có nghĩa là hệ thống của bạn hoạt động tốt; nó có nghĩa là tất cả các bài kiểm tra của bạn đang vượt qua . Điều đó có nghĩa là các phần trong thiết kế của bạn mà bạn có ý nghĩ và viết các bài kiểm tra đang hoạt động như bạn nghĩ chúng có ý thức, dù sao đó thực sự không phải là vấn đề lớn: đó là thứ mà bạn thực sự chú ý đến, vì vậy rất có thể bạn đã hiểu đúng! Nhưng nó không có gì để bắt những trường hợp bạn chưa từng nghĩ đến, chẳng hạn như trường hợp này, bởi vì bạn chưa bao giờ nghĩ sẽ viết một bài kiểm tra cho họ. (Và nếu bạn có, bạn đã nhận ra rằng điều đó có nghĩa là thay đổi mã là cần thiết và bạn đã thay đổi chúng.)


17
Cha tôi thường hỏi tôi rằng: Tại sao con không nghĩ đến điều con không nghĩ đến? (Chỉ có anh ấy từng làm cho nó khó hiểu bằng cách nói "Nếu bạn không biết, hãy hỏi !") Nhưng làm sao tôi biết rằng tôi không biết?

7
"Điều đó có nghĩa là các phần trong thiết kế của bạn mà bạn có ý nghĩ và viết các bài kiểm tra đang hoạt động như bạn nghĩ chúng sẽ có ý thức." Hoàn toàn chính xác. Thông tin này là vô giá nếu bạn đang tái cấu trúc hoặc nếu có gì đó thay đổi ở một nơi khác trong hệ thống phá vỡ các giả định của bạn. Các nhà phát triển bị ru ngủ trong một cảm giác an toàn sai lầm chỉ đơn giản là không hiểu những hạn chế của kiểm thử đơn vị, nhưng điều đó không khiến đơn vị kiểm tra một công cụ vô dụng.
Robert Harvey

12
@MasonWheeler: Giống như bạn, tác giả nghĩ rằng thử nghiệm đơn vị bằng cách nào đó được cho là để chứng minh rằng chương trình của bạn hoạt động. Nó không. Hãy để tôi nhắc lại rằng: kiểm thử đơn vị không chứng minh rằng chương trình của bạn hoạt động. Kiểm thử đơn vị chứng minh rằng các phương thức của bạn hoàn thành hợp đồng thử nghiệm của bạn và đó là tất cả những gì nó làm. Phần còn lại của bài báo rơi xuống, bởi vì nó nằm trên tiền đề không hợp lệ duy nhất đó.
Robert Harvey

5
Đương nhiên, các nhà phát triển có niềm tin sai lầm sẽ thất vọng khi thử nghiệm đơn vị hoàn toàn không thành công, nhưng đó là lỗi của nhà phát triển, không phải thử nghiệm đơn vị và không làm mất giá trị chính hãng mà thử nghiệm đơn vị cung cấp.
Robert Harvey

5
o_O @ câu đầu tiên của bạn. Các bài kiểm tra đơn vị cung cấp cho bạn cảm giác an toàn sai lầm trong khi mã hóa như đặt tay lên vô lăng cho bạn cảm giác an toàn sai lầm khi lái xe.
djechlin

10

Không, không nhất thiết.

Yêu cầu ban đầu là sử dụng mã nhánh số, do đó, một bài kiểm tra đơn vị sẽ được tạo ra cho một thành phần chấp nhận các mã khác nhau và từ chối bất kỳ mã nào giống như 10B. Hệ thống sẽ được thông qua như đang hoạt động (đó là nó).

Sau đó, yêu cầu sẽ thay đổi và mã được cập nhật, nhưng điều này có nghĩa là mã kiểm tra đơn vị cung cấp dữ liệu xấu (hiện là dữ liệu tốt) sẽ phải được sửa đổi.

Bây giờ chúng tôi giả định rằng, những người quản lý hệ thống sẽ biết đây là trường hợp và sẽ thay đổi thử nghiệm đơn vị để xử lý mã mới ... nhưng nếu họ biết điều đó xảy ra, họ cũng sẽ biết thay đổi mã đã xử lý các mã này mã nào .. và họ đã không làm điều đó. Một bài kiểm tra đơn vị ban đầu đã từ chối mã 10B sẽ vui vẻ nói rằng "mọi thứ đều ổn ở đây" khi chạy, nếu bạn không biết cập nhật bài kiểm tra đó.

Kiểm thử đơn vị là tốt cho phát triển ban đầu nhưng không phải để kiểm tra hệ thống, đặc biệt là không 15 năm sau khi các yêu cầu bị lãng quên từ lâu.

Những gì họ cần trong loại tình huống này là một thử nghiệm tích hợp đầu cuối. Một nơi bạn có thể truyền dữ liệu mà bạn mong đợi để làm việc và xem liệu nó có hoạt động không. Ai đó sẽ nhận thấy rằng dữ liệu đầu vào mới của họ không tạo ra một báo cáo và sau đó sẽ điều tra thêm.


Tại chỗ trên. Và vấn đề chính (chỉ?) Với các bài kiểm tra đơn vị. Lưu lại cho tôi từ ngữ câu trả lời của riêng tôi, vì tôi đã nói chính xác điều tương tự (nhưng có lẽ tệ hơn!) :)
Các cuộc đua nhẹ nhàng trong quỹ đạo

8

Kiểm thử loại (quá trình kiểm tra các bất biến sử dụng dữ liệu hợp lệ được tạo ngẫu nhiên, như được minh họa bởi thư viện kiểm tra Haskell QuickCheck và các cổng / giải pháp thay thế khác được lấy cảm hứng từ các ngôn ngữ khác) có thể đã gặp phải vấn đề này, kiểm thử đơn vị gần như chắc chắn sẽ không được thực hiện .

Điều này là do khi các quy tắc về tính hợp lệ của mã chi nhánh được cập nhật, không có ai có thể nghĩ sẽ kiểm tra các phạm vi cụ thể đó để đảm bảo chúng hoạt động chính xác.

Tuy nhiên, nếu loại thử nghiệm đã được sử dụng, ai đó nên tại thời điểm hệ thống ban đầu được triển khai đã viết một cặp tài sản, một để kiểm tra xem các mã cụ thể đối với các ngành kiểm tra được coi là dữ liệu thử nghiệm và một để kiểm tra rằng không có mã khác là ... khi định nghĩa kiểu dữ liệu cho mã chi nhánh được cập nhật (điều này sẽ được yêu cầu để cho phép kiểm tra xem có bất kỳ thay đổi nào đối với mã nhánh từ chữ số sang số đã hoạt động không), thử nghiệm này đã bắt đầu thử nghiệm các giá trị trong phạm vi mới và rất có thể đã xác định được lỗi.

Tất nhiên, QuickCheck được phát triển lần đầu tiên vào năm 1999, vì vậy đã quá muộn để nắm bắt vấn đề này.


1
Tôi nghĩ việc gọi thử nghiệm dựa trên thuộc tính này là bình thường hơn và tất nhiên là có thể viết một thử nghiệm dựa trên thuộc tính vẫn có thể vượt qua thay đổi này (mặc dù tôi nghĩ rằng bạn có nhiều khả năng viết thử nghiệm có thể tìm thấy nó)
jk.

5

Tôi thực sự nghi ngờ thử nghiệm đơn vị sẽ làm cho một sự khác biệt cho vấn đề này. Nghe có vẻ như một trong những tình huống tầm nhìn đường hầm vì chức năng đã được thay đổi để hỗ trợ mã chi nhánh mới, nhưng điều này không được thực hiện trên tất cả các khu vực trong hệ thống.

Chúng tôi sử dụng thử nghiệm đơn vị để thiết kế một lớp. Chạy lại một bài kiểm tra đơn vị chỉ được yêu cầu nếu thiết kế đã thay đổi. Nếu một đơn vị cụ thể không thay đổi, thì các bài kiểm tra đơn vị không thay đổi sẽ trả về kết quả như trước. Các bài kiểm tra đơn vị sẽ không cho bạn thấy tác động của các thay đổi đối với các đơn vị khác (nếu họ không viết bài kiểm tra đơn vị).

Bạn chỉ có thể phát hiện vấn đề này một cách hợp lý thông qua:

  • Kiểm tra tích hợp - nhưng bạn sẽ phải thêm cụ thể các định dạng mã mới để cung cấp thông qua nhiều đơn vị trong hệ thống (nghĩa là chúng sẽ chỉ cho bạn biết vấn đề nếu các kiểm tra ban đầu bao gồm các nhánh hiện có hiệu lực)
  • Thử nghiệm đầu cuối - doanh nghiệp nên chạy thử nghiệm đầu cuối kết hợp các định dạng mã chi nhánh cũ và mới

Không có đủ thử nghiệm đầu cuối là đáng lo ngại hơn. Bạn không thể dựa vào kiểm tra đơn vị vì kiểm tra CHỈ hoặc CHÍNH của bạn để thay đổi hệ thống. Có vẻ như nó chỉ yêu cầu ai đó chạy báo cáo về các định dạng mã ngành mới được hỗ trợ.


2

Một xác nhận tích hợp trong thời gian chạy có thể có ích; ví dụ:

  1. Tạo một chức năng như bool isTestOnly(string branchCode) { ... }
  2. Sử dụng chức năng này để quyết định báo cáo nào cần lọc ra
  3. Sử dụng lại chức năng đó trong một xác nhận, trong mã tạo chi nhánh, để xác minh hoặc khẳng định rằng một nhánh không (không thể) được tạo bằng loại mã chi nhánh này
  4. Có xác nhận này được bật trong thời gian thực (và không được "tối ưu hóa ngoại trừ trong phiên bản mã dành cho nhà phát triển chỉ gỡ lỗi")

Xem thêm:


2

Việc mua lại từ đây là Thất bại nhanh .

Chúng tôi không có mã, chúng tôi cũng không có nhiều ví dụ về các tiền tố đang hoặc không phải là tiền tố nhánh thử nghiệm theo mã. Tất cả chúng ta có là đây:

  • 089 - 100 => chi nhánh kiểm tra
  • 10B, 10C => nhánh thử nghiệm
  • <088 => có lẽ là các chi nhánh thực
  • > 100 => có lẽ là chi nhánh thực

Thực tế là mã cho phép số và chuỗi nhiều hơn một chút lạ. Tất nhiên, 10B và 10C có thể được coi là số hex, nhưng nếu tất cả các tiền tố được coi là số hex, 10B và 10C nằm ngoài phạm vi thử nghiệm và sẽ được coi là các nhánh thực.

Điều này có thể có nghĩa là tiền tố được lưu trữ dưới dạng một chuỗi nhưng được coi là một số trong một số trường hợp. Đây là mã đơn giản nhất tôi có thể nghĩ ra để sao chép hành vi này (sử dụng C # cho mục đích minh họa):

bool IsTest(string strPrefix) {
    int iPrefix;
    if(int.TryParse(strPrefix, out iPrefix))
        return iPrefix >= 89 && iPrefix <= 100;
    return true; //here is the problem
}

Trong tiếng Anh, nếu chuỗi là một số và nằm trong khoảng từ 89 đến 100, thì đó là một bài kiểm tra. Nếu nó không phải là một con số, nó là một bài kiểm tra. Nếu không, nó không phải là một bài kiểm tra.

Nếu mã theo mẫu này, sẽ không có thử nghiệm đơn vị nào bắt được điều này tại thời điểm mã được triển khai. Dưới đây là một số ví dụ kiểm tra đơn vị:

assert.isFalse(IsTest("088"))
assert.isTrue(IsTest("089"))
assert.isTrue(IsTest("095"))
assert.isTrue(IsTest("100"))
assert.isFalse(IsTest("101"))
assert.isTrue(IsTest("10B")) // <--- business rule change

Thử nghiệm đơn vị cho thấy "10B" nên được coi là một nhánh thử nghiệm. Người dùng @ gnasher729 ở trên nói rằng các quy tắc kinh doanh đã thay đổi và đó là những gì khẳng định cuối cùng ở trên cho thấy. Tại một số điểm mà khẳng định lẽ ra đã chuyển sang một isFalse, nhưng điều đó đã không xảy ra. Các bài kiểm tra đơn vị được chạy ở thời điểm phát triển và xây dựng nhưng sau đó không có điểm nào sau đó.


Bài học ở đây là gì? Mã cần một số cách để báo hiệu rằng nó đã nhận được đầu vào bất ngờ. Đây là một cách khác để viết mã này nhấn mạnh rằng nó hy vọng tiền tố là một số:

// Alternative A
bool TryGetIsTest(string strPrefix, out bool isTest) {
    int iPrefix;
    if(int.TryParse(strPrefix, out iPrefix)) {
        isTest = iPrefix >= 89 && iPrefix <= 100;
        return true;
    }
    isTest = true; //this is just some value that won't be read
    return false;
}

Đối với những người không biết C #, giá trị trả về cho biết mã có thể phân tích tiền tố từ chuỗi đã cho hay không. Nếu giá trị trả về là true, mã gọi có thể sử dụng biến isTest out để kiểm tra xem tiền tố nhánh có phải là tiền tố kiểm tra hay không. Nếu giá trị trả về là sai, mã gọi sẽ báo cáo rằng tiền tố đã cho không được mong đợi và biến isTest out là vô nghĩa và nên được bỏ qua.

Nếu bạn ổn với ngoại lệ, bạn có thể làm điều này thay vào đó:

// Alternative B
bool IsTest(string strPrefix) {
    int iPrefix = int.Parse(strPrefix);
    return iPrefix >= 89 && iPrefix <= 100;
}

Sự thay thế này là đơn giản hơn. Trong trường hợp này, mã gọi cần phải bắt ngoại lệ. Trong cả hai trường hợp, mã nên có một số cách báo cáo cho người gọi rằng nó không mong đợi một strPrefix không thể được chuyển đổi thành một số nguyên. Bằng cách này, mã thất bại nhanh chóng và ngân hàng có thể nhanh chóng tìm ra vấn đề mà không có sự bối rối tốt của SEC.


1

Rất nhiều câu trả lời và thậm chí không một trích dẫn của Dijkstra:

Thử nghiệm cho thấy sự hiện diện, không phải là không có lỗi.

Do đó, nó phụ thuộc. Nếu mã được kiểm tra đúng cách, rất có thể lỗi này sẽ không tồn tại.


-1

Tôi nghĩ rằng một bài kiểm tra đơn vị ở đây sẽ đảm bảo vấn đề không bao giờ tồn tại ở nơi đầu tiên.

Hãy xem xét, bạn đã viết bool IsTestData(string branchCode)chức năng.

Bài kiểm tra đơn vị đầu tiên bạn viết nên dành cho chuỗi rỗng và chuỗi rỗng. Sau đó cho các chuỗi có độ dài không chính xác sau đó cho các chuỗi không nguyên.

Để thực hiện tất cả các bài kiểm tra đó, bạn sẽ phải thêm kiểm tra tham số cho hàm.

Ngay cả khi bạn chỉ kiểm tra dữ liệu 'tốt' 001 -> 999 không nghĩ về khả năng 10A, việc kiểm tra tham số sẽ buộc bạn phải viết lại chức năng khi bạn bắt đầu sử dụng chữ và số để tránh các ngoại lệ mà nó sẽ ném


1
Điều này sẽ không có ích - chức năng không bị thay đổi và thử nghiệm sẽ không bắt đầu thất bại với cùng một dữ liệu thử nghiệm. Ai đó sẽ phải nghĩ đến việc thay đổi bài kiểm tra để khiến nó thất bại, nhưng nếu họ nghĩ về điều đó, có lẽ họ cũng đã nghĩ đến việc thay đổi chức năng.
Hulk

(Hoặc có lẽ tôi đang thiếu một cái gì đó, vì tôi không chắc ý của bạn là gì khi "kiểm tra tham số")
Hulk

Hàm sẽ bị buộc phải ném một ngoại lệ cho các chuỗi không nguyên số để vượt qua bài kiểm tra đơn vị trường hợp cạnh đơn giản. Do đó, mã sản xuất sẽ bị lỗi nếu bạn bắt đầu sử dụng mã nhánh chữ và số mà không lập trình cụ thể cho chúng
Ewan

Nhưng chức năng đã sử dụng một số IsValidBranchCodechức năng để thực hiện kiểm tra này? Và chức năng này có lẽ đã được thay đổi mà không cần phải sửa đổi IsTestData? Vì vậy, nếu bạn chỉ kiểm tra 'dữ liệu tốt' thì bài kiểm tra sẽ không có ích. Kiểm tra trường hợp cạnh sẽ phải bao gồm một số mã chi nhánh hợp lệ hiện tại (và không chỉ đơn giản là một số vẫn còn không hợp lệ) để bắt đầu thất bại.
Hulk

1
Nếu kiểm tra nằm trong IsValidCode, để chức năng vượt qua mà không có kiểm tra rõ ràng, thì có thể bỏ lỡ nó, nhưng sau đó chúng ta sẽ có thêm một loạt các thử nghiệm nữa, giả định Trình xác thực, v.v. số kiểm tra "
Ewan
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.