Có bảo hiểm đường dẫn đảm bảo tìm thấy tất cả các lỗi?


64

Nếu mọi đường dẫn thông qua một chương trình được kiểm tra, điều đó có đảm bảo tìm thấy tất cả các lỗi không?

Nếu không, tai sao không? Làm thế nào bạn có thể đi qua mọi sự kết hợp có thể của dòng chương trình và không tìm thấy vấn đề nếu tồn tại?

Tôi ngần ngại đề xuất rằng "tất cả các lỗi" có thể được tìm thấy, nhưng có lẽ đó là do phạm vi bảo hiểm đường dẫn không thực tế (vì nó là tổ hợp) nên nó chưa từng có kinh nghiệm?

Lưu ý: bài viết này cung cấp một bản tóm tắt nhanh chóng về các loại bảo hiểm như tôi nghĩ về chúng.


33
Điều này tương đương với vấn đề tạm dừng .

31
Điều gì nếu mã nên có ở đó, không?
RemcoGerlich 30/03/2015

6
@Snowman: Không, không phải vậy. Không thể giải quyết vấn đề tạm dừng cho tất cả các chương trình nhưng đối với nhiều chương trình cụ thể thì có thể giải quyết được. Đối với các chương trình này, tất cả các đường dẫn mã có thể được liệt kê trong một khoảng thời gian hữu hạn (mặc dù có thể dài).
Jørgen Fogh

3
@ JørgenFogh Nhưng khi cố gắng tìm lỗi trong bất kỳ chương trình nào , đó có phải là một tiên nghiệm không biết chương trình có dừng lại hay không? Đây không phải là câu hỏi về phương pháp chung "tìm tất cả các lỗi trong bất kỳ chương trình nào thông qua bảo hiểm đường dẫn"? Trong trường hợp nào, nó không giống với "tìm kiếm bất kỳ chương trình nào dừng lại"?
Andres F.

1
@AresresF. nó chỉ là không biết nếu chương trình dừng lại nếu tập hợp con của ngôn ngữ mà nó được viết có khả năng diễn đạt một chương trình không dừng lại. Nếu chương trình của bạn được viết bằng C mà không sử dụng các vòng lặp / đệ quy / setjmp không liên kết, v.v., hoặc trong Coq, hoặc trong ESSL, thì nó phải dừng lại và tất cả các đường dẫn có thể được theo dõi. (Turing-đầy đủ được đánh giá nghiêm túc)
Leushenko

Câu trả lời:


128

Nếu mọi đường dẫn thông qua một chương trình được kiểm tra, điều đó có đảm bảo tìm thấy tất cả các lỗi không?

Không

Nếu không, tai sao không? Làm thế nào bạn có thể đi qua mọi sự kết hợp có thể của dòng chương trình và không tìm thấy vấn đề nếu tồn tại?

Bởi vì ngay cả khi bạn kiểm tra tất cả các đường dẫn có thể , bạn vẫn chưa kiểm tra chúng với tất cả các giá trị có thể hoặc tất cả các kết hợp giá trị có thể . Ví dụ (mã giả):

def Add(x as Int32, y as Int32) as Int32:
   return x + y

Test.Assert(Add(2, 2) == 4) //100% test coverage
Add(MAXINT, 5) //Throws an exception, despite 100% test coverage

Bây giờ là hai thập kỷ kể từ khi chỉ ra rằng thử nghiệm chương trình có thể chứng minh một cách thuyết phục sự hiện diện của lỗi, nhưng không bao giờ có thể chứng minh sự vắng mặt của chúng. Sau khi trích dẫn lời nhận xét được công bố rộng rãi này, kỹ sư phần mềm trở lại trật tự trong ngày và tiếp tục hoàn thiện các chiến lược thử nghiệm của mình, giống như nhà giả kim của yore, người tiếp tục tinh chỉnh các tinh chế chrysocosmic của mình.

- EW Dijkstra (Nhấn mạnh thêm. Được viết vào năm 1988. Đã hơn 2 thập kỷ rồi.)


7
@digitgopher: Tôi cho rằng, nhưng nếu một chương trình không có đầu vào, thì nó có ích gì?
Mason Wheeler

34
Ngoài ra còn có khả năng thiếu các bài kiểm tra tích hợp, lỗi trong các bài kiểm tra, lỗi về sự phụ thuộc, lỗi trong hệ thống xây dựng / triển khai hoặc lỗi trong đặc tả / yêu cầu ban đầu. Bạn không bao giờ có thể đảm bảo tìm thấy tất cả các lỗi.
Ixrec

11
@Ixrec: Mặc dù vậy, SQLite là một nỗ lực tuyệt vời! Nhưng hãy nhìn xem đó là một nỗ lực to lớn! Điều đó sẽ không mở rộng tốt cho các cơ sở mã lớn.
Mason Wheeler

13
Bạn không chỉ không kiểm tra tất cả các giá trị hoặc kết hợp có thể, mà bạn chưa kiểm tra tất cả các thời gian tương đối, một số trong đó có thể phơi bày các điều kiện cuộc đua hoặc thực sự làm cho bài kiểm tra của bạn rơi vào bế tắc, khiến nó không thể báo cáo bất cứ điều gì . Nó thậm chí sẽ không thành công!
Idillotexist Idonotexist 30/03/2015

14
Hồi ức của tôi (được hỗ trợ bởi các bài viết như thế này ) là Dijkstra tin rằng trong thực tiễn lập trình tốt, bằng chứng cho thấy một chương trình là chính xác (trong mọi điều kiện) nên là một phần không thể thiếu trong quá trình phát triển chương trình. Nhìn từ quan điểm đó, thử nghiệm giống như thuật giả kim. Thay vì cường điệu, tôi nghĩ rằng đây là một ý kiến ​​rất mạnh mẽ được thể hiện bằng ngôn ngữ rất mạnh mẽ.
David K

71

Ngoài câu trả lời của Mason , còn có một vấn đề khác: phạm vi bảo hiểm không cho bạn biết mã nào đã được kiểm tra, nó cho bạn biết mã nào đã được thực thi .

Hãy tưởng tượng bạn có một testsuite với phạm vi bảo hiểm 100% đường dẫn. Bây giờ loại bỏ tất cả các xác nhận và chạy lại testsuite. Voilà, testsuite vẫn có phạm vi bảo hiểm 100% đường dẫn, nhưng nó kiểm tra hoàn toàn không có gì.


2
Nó có thể đảm bảo rằng không có ngoại lệ khi gọi mã được kiểm tra (với các tham số trong thử nghiệm). Điều này là hơi nhiều hơn không có gì.
Paŭlo Ebermann

7
@ PaŭloEbermann Đồng ý, hơi nhiều hơn không có gì. Tuy nhiên, nó ít hơn nhiều so với "tìm tất cả các lỗi";)
Andres F.

1
@ PaŭloEbermann: Ngoại lệ là một đường dẫn mã. Nếu mã có thể ném nhưng với dữ liệu thử nghiệm nhất định không ném, thử nghiệm không đạt được phạm vi bao phủ 100% đường dẫn. Điều này không cụ thể đối với các trường hợp ngoại lệ như là một cơ chế xử lý lỗi. Visual Basic của ON ERROR GOTOcũng là một con đường, như là C if(errno).
MSalters

1
@MSalters Tôi đang nói về mã mà (theo đặc tả) không nên ném bất kỳ ngoại lệ nào, bất kể đầu vào là gì. Nếu nó ném bất kỳ, đó sẽ là một lỗi. Tất nhiên, nếu bạn có mã được chỉ định để ném ngoại lệ, thì mã đó sẽ được kiểm tra. (Và tất nhiên, như Jörg đã nói, chỉ cần kiểm tra xem mã không ném ngoại lệ thường là không đủ để đảm bảo nó làm đúng, ngay cả đối với mã không ném.) Và một số trường hợp ngoại lệ có thể bị ném bởi đường dẫn mã -visible, như đối với việc bổ sung con trỏ null hoặc chia cho số không. Công cụ bảo hiểm đường dẫn của bạn có bắt được chúng không?
Paŭlo Ebermann

2
Câu trả lời này đinh. Tôi sẽ đưa ra yêu cầu thậm chí xa hơn và nói rằng do điều này, phạm vi bảo hiểm đường dẫn không bao giờ đảm bảo tìm thấy ngay cả một lỗi. Tuy nhiên, có những số liệu có thể đảm bảo ít nhất là những thay đổi sẽ được phát hiện, tuy nhiên - kiểm tra đột biến thực sự có thể đảm bảo rằng (một số) sửa đổi mã sẽ được phát hiện.
eis

34

Đây là một ví dụ đơn giản hơn để làm tròn mọi thứ. Hãy xem xét thuật toán sắp xếp sau (trong Java):

int[] sort(int[] x) { return new int[] { x[0] }; }

Bây giờ, hãy kiểm tra:

sort(new int[] { 0xCAFEBABE });

Bây giờ, hãy xem xét rằng (A) lệnh gọi cụ thể này để sorttrả về kết quả chính xác, (B) tất cả các đường dẫn mã đã được kiểm tra này.

Nhưng, rõ ràng, chương trình không thực sự sắp xếp.

Theo sau đó, phạm vi bảo hiểm của tất cả các đường dẫn mã là không đủ để đảm bảo rằng chương trình không có lỗi.


12

Hãy xem xét abshàm, trả về giá trị tuyệt đối của một số. Đây là một bài kiểm tra (Python, hãy tưởng tượng một số khung kiểm tra):

def test_abs_of_neg_number_returns_positive():
    assert abs(-3) == 3

Cách thực hiện này là chính xác, nhưng nó chỉ được bảo hiểm mã 60%:

def abs(x):
    if x < 0:
        return -x
    else:
        return x

Việc triển khai này là sai, nhưng nó được bảo hiểm 100% mã:

def abs(x):
    return -x

2
Đây là một triển khai khác vượt qua bài kiểm tra (xin vui lòng bỏ qua Python không có dòng): def abs(x): if x == -3: return 3 else: return 0Bạn có thể bỏ qua else: return 0phần đó và được bảo hiểm 100%, nhưng về cơ bản, chức năng này sẽ vô dụng mặc dù nó vượt qua bài kiểm tra đơn vị.
CVn

7

Một bổ sung khác cho câu trả lời của Mason , hành vi của một chương trình có thể phụ thuộc vào môi trường thời gian chạy.

Đoạn mã sau có chứa Sử dụng sau khi miễn phí:

int main(void)
{
    int* a = malloc(sizeof(a));
    int* b = a;
    *a = 0;
    free(a);
    *b = 12; /* UAF */
    return 0;
}

Mã này là Hành vi không xác định, tùy thuộc vào cấu hình (phát hành | gỡ lỗi), HĐH và trình biên dịch, nó sẽ mang lại các hành vi khác nhau. Không chỉ phạm vi bảo hiểm đường dẫn sẽ không đảm bảo rằng bạn sẽ tìm thấy UAF, mà bộ kiểm tra của bạn thường sẽ không bao gồm các hành vi có thể khác nhau của UAF phụ thuộc vào cấu hình.

Một lưu ý khác, ngay cả khi phạm vi bảo hiểm đường dẫn là để đảm bảo tìm thấy tất cả các lỗi, không chắc là nó có thể đạt được trong thực tế trên bất kỳ chương trình nào. Hãy xem xét một trong những điều sau đây:

int main(int a, int b)
{
    if (a != b) {
        if (cryptohash(a) == cryptohash(b)) {
            return ERROR;
        }
    }
    return 0;
} 

Nếu bộ thử nghiệm của bạn có thể tạo ra tất cả các đường dẫn cho việc này, thì xin chúc mừng bạn là một nhà mật mã học.


Dễ dàng cho các số nguyên đủ nhỏ :)
CodeInChaos 30/03/2015

Không biết gì về cryptohashnó, thật khó để nói "đủ nhỏ" là gì. Có lẽ phải mất hai ngày để hoàn thành một siêu máy tính. Nhưng vâng, intcó thể là một chút short.
dureuill

Với số nguyên 32 bit và băm mật mã điển hình (SHA2, SHA3, v.v.) tính toán, điều này sẽ khá rẻ. Một vài giây hoặc lâu hơn.
CodeInChaos

7

Rõ ràng từ các câu trả lời khác rằng độ bao phủ mã 100% trong các thử nghiệm không có nghĩa là độ chính xác của mã 100% hoặc thậm chí tất cả các lỗi có thể tìm thấy bằng thử nghiệm sẽ được tìm thấy (không bao giờ để ý các lỗi mà không thử nghiệm nào có thể bắt được).

Một cách khác để trả lời câu hỏi này là một từ thực tiễn:

Trong thế giới thực và trên máy tính của bạn, có rất nhiều phần mềm được phát triển bằng một bộ kiểm tra có độ bao phủ 100% và vẫn còn lỗi, bao gồm cả các lỗi mà kiểm tra tốt hơn sẽ xác định.

Do đó, một câu hỏi đòi hỏi là:

Điểm của các công cụ bảo hiểm mã là gì?

Các công cụ bảo hiểm mã giúp xác định các khu vực mà người ta đã bỏ qua để kiểm tra. Điều đó có thể ổn (mã hoàn toàn chính xác ngay cả khi không kiểm tra) không thể giải quyết (vì lý do nào đó đường dẫn không thể bị tấn công) hoặc có thể là vị trí của một lỗi hôi thối tuyệt vời ngay bây giờ hoặc sau các sửa đổi trong tương lai.

Trong một số cách, kiểm tra chính tả có thể so sánh được: Một cái gì đó có thể "vượt qua" kiểm tra chính tả và bị sai chính tả theo cách khớp với một từ trong từ điển. Hoặc nó có thể "thất bại" vì các từ chính xác không có trong từ điển. Hoặc nó có thể vượt qua và vô nghĩa. Kiểm tra chính tả là một công cụ giúp bạn xác định các địa điểm mà bạn có thể đã bỏ lỡ trong quá trình đọc bằng chứng của mình, nhưng cũng như nó không thể đảm bảo việc đọc bằng chứng hoàn chỉnh và chính xác, do đó, phạm vi bảo hiểm mã không thể đảm bảo kiểm tra đầy đủ và chính xác.

Và tất nhiên, cách sử dụng kiểm tra chính tả không chính xác là nổi tiếng với mọi gợi ý về biển mà nó gợi ý để điều vịt trở nên tồi tệ hơn sau đó nếu chúng tôi cho nó mượn.

Với phạm vi bảo hiểm mã, nó có thể hấp dẫn, đặc biệt là nếu bạn đã hoàn thành 98%, để điền vào các trường hợp để các đường dẫn còn lại bị tấn công.

Đó là tương đương với quyền với kiểm tra chính tả rằng tất cả các từ thời tiết hoặc thắt nút đó là tất cả các từ thích hợp. Kết quả là một mớ hỗn độn vịt.

Tuy nhiên, nếu bạn xem xét những gì kiểm tra các đường dẫn không được bảo hiểm thực sự cần, công cụ bao phủ mã sẽ thực hiện công việc của nó; không phải trong việc hứa hẹn cho bạn sự đúng đắn, nhưng nó chỉ ra một số công việc cần phải làm.


+1 Tôi thích câu trả lời này vì nó mang tính xây dựng và đề cập đến một số lợi ích của bảo hiểm.
Andres F.

4

Bảo hiểm đường dẫn không thể cho bạn biết liệu tất cả các tính năng cần thiết đã được triển khai chưa. Rời khỏi một tính năng là một lỗi, nhưng phạm vi bảo hiểm đường dẫn sẽ không phát hiện ra nó.


1
Tôi nghĩ rằng điều đó phụ thuộc vào định nghĩa của một lỗi. Tôi không nghĩ rằng các tính năng hoặc chức năng bị thiếu nên được coi là lỗi.
eis

@eis - bạn không thấy có vấn đề gì với một sản phẩm có tài liệu nói rằng nó làm X khi thực tế nó không có? Đó là một định nghĩa khá hẹp về "lỗi". Khi tôi quản lý QA cho dòng sản phẩm C ++ của Borland, chúng tôi không hào phóng.
Pete Becker

Tôi không thấy lý do tại sao tài liệu lại nói nó làm X nếu điều đó không bao giờ được thực hiện
eis

@eis - nếu thiết kế ban đầu được gọi là tính năng X, tài liệu có thể kết thúc mô tả tính năng X. Nếu không ai thực hiện nó, đó là một lỗi và phạm vi bảo hiểm đường dẫn (hoặc bất kỳ loại thử nghiệm hộp đen nào khác) sẽ không tìm thấy nó.
Pete Becker

Rất tiếc, phạm vi bảo hiểm là kiểm tra hộp trắng , không phải hộp đen . Kiểm tra hộp trắng không thể bắt các tính năng bị thiếu.
Pete Becker

4

Một phần của vấn đề là phạm vi bảo hiểm 100% chỉ đảm bảo rằng mã sẽ hoạt động chính xác sau một lần thực thi . Một số lỗi như rò rỉ bộ nhớ có thể không rõ ràng hoặc gây ra sự cố sau một lần thực thi, nhưng theo thời gian sẽ gây ra sự cố cho ứng dụng.

Ví dụ: giả sử bạn có một ứng dụng kết nối với cơ sở dữ liệu. Có lẽ trong một phương thức, lập trình viên quên đóng kết nối với cơ sở dữ liệu khi chúng được thực hiện với truy vấn của họ. Bạn có thể chạy một số thử nghiệm qua phương pháp này và không tìm thấy lỗi nào với chức năng của nó, nhưng máy chủ cơ sở dữ liệu của bạn có thể gặp phải tình huống không có kết nối khả dụng vì phương thức cụ thể này không đóng kết nối khi hoàn thành và các kết nối mở phải bây giờ đã hết thời gian


Đồng ý rằng đó là một phần của vấn đề, nhưng vấn đề thực sự còn cơ bản hơn thế. Ngay cả với một máy tính lý thuyết có bộ nhớ vô hạn và không có sự tương tranh, phạm vi kiểm tra 100% không có nghĩa là không có lỗi. Các ví dụ tầm thường về rất nhiều câu trả lời ở đây, nhưng đây là một ví dụ khác: nếu chương trình của tôi là times_two(x) = x + 2, phần này sẽ được bao phủ hoàn toàn bởi bộ thử nghiệm assert(times_two(2) == 4), nhưng đây rõ ràng vẫn là mã lỗi! Không cần rò rỉ bộ nhớ :)
Andres F.

2
Đó là một điểm tuyệt vời và tôi nhận ra rằng đó là một cái đinh lớn hơn / cơ bản hơn trong quan tài về khả năng của các ứng dụng không có lỗi, nhưng như bạn nói nó đã được thêm vào đây và tôi muốn thêm một cái gì đó không được đề cập đến câu trả lời hiện có. Tôi đã nghe nói về các ứng dụng bị sập vì các kết nối cơ sở dữ liệu không được phát hành trở lại nhóm kết nối khi chúng không còn cần thiết - Rò rỉ bộ nhớ chỉ là ví dụ điển hình của việc quản lý tài nguyên sai. Quan điểm của tôi là thêm rằng việc quản lý tài nguyên nói chung không thể được kiểm tra hoàn toàn.
Derek W

Điểm tốt. Đã đồng ý.
Andres F.

3

Nếu mọi đường dẫn thông qua một chương trình được kiểm tra, điều đó có đảm bảo tìm thấy tất cả các lỗi không?

Như đã nói, câu trả lời là KHÔNG.

Nếu không, tai sao không?

Bên cạnh những gì đang được nói, có những lỗi xuất hiện ở các cấp độ khác nhau, không thể được kiểm tra bằng các bài kiểm tra đơn vị. Chỉ cần đề cập đến một vài:

  • lỗi bắt gặp với kiểm tra tích hợp (xét nghiệm đơn vị không nên sử dụng tài nguyên thực sự)
  • lỗi trong yêu cầu
  • lỗi trong thiết kế và kiến ​​trúc

2

Nó có ý nghĩa gì đối với mọi con đường được thử nghiệm?

Các câu trả lời khác là rất tốt, nhưng tôi chỉ muốn thêm rằng điều kiện "mọi con đường thông qua một chương trình được kiểm tra" là rất mơ hồ.

Hãy xem xét phương pháp này:

def add(num1, num2)
  foo = "bar"  # useless statement
  $global += 1 # side effect
  num1 + num2  # actual work
end

Nếu bạn viết một bài kiểm tra khẳng định add(1, 2) == 3, một công cụ bao phủ mã sẽ cho bạn biết rằng mọi dòng đều được thực hiện. Nhưng bạn chưa thực sự khẳng định bất cứ điều gì về tác dụng phụ toàn cầu hoặc nhiệm vụ vô ích. Những dòng đó được thực thi, nhưng chưa thực sự được thử nghiệm.

Thử nghiệm đột biến sẽ giúp tìm ra các vấn đề như thế này. Một công cụ kiểm tra đột biến sẽ có một danh sách các cách được xác định trước để "biến đổi" mã và xem các kiểm tra có còn vượt qua hay không. Ví dụ:

  • Một đột biến có thể thay đổi +=thành -=. Đột biến đó sẽ không gây ra lỗi thử nghiệm, vì vậy nó sẽ chứng minh rằng thử nghiệm của bạn không khẳng định bất cứ điều gì có ý nghĩa về tác dụng phụ toàn cầu.
  • Một đột biến khác có thể xóa dòng đầu tiên. Đột biến đó sẽ không gây ra lỗi kiểm tra, vì vậy nó sẽ chứng minh rằng bài kiểm tra của bạn không khẳng định bất cứ điều gì có ý nghĩa về bài tập.
  • Vẫn còn một đột biến khác có thể xóa dòng thứ ba. Điều đó sẽ gây ra lỗi thử nghiệm, trong trường hợp này, cho thấy thử nghiệm của bạn không khẳng định điều gì về dòng đó.

Trong essense, kiểm tra đột biến là một cách để kiểm tra bài kiểm tra của bạn . Nhưng giống như bạn sẽ không bao giờ kiểm tra chức năng thực tế với mọi bộ đầu vào có thể, bạn sẽ không bao giờ chạy mọi đột biến có thể xảy ra, do đó, điều này lại bị hạn chế.

Mỗi thử nghiệm chúng tôi có thể làm là một heuristic để tiến tới các chương trình không có lỗi. Không có gì là hoàn hảo.


0

Chà ... đúng vậy , nếu mọi đường dẫn thông qua chương trình được thử nghiệm. Nhưng điều đó có nghĩa là, mọi con đường có thể đi qua toàn bộ không gian của tất cả các trạng thái có thể mà chương trình có thể có, bao gồm tất cả các biến. Ngay cả đối với một chương trình được biên dịch tĩnh rất đơn giản - giả sử, một cruncher số Fortran cũ - không khả thi, mặc dù ít nhất có thể tưởng tượng được: nếu bạn chỉ có hai biến số nguyên, về cơ bản bạn đang xử lý tất cả các cách có thể để kết nối các điểm trên lưới hai chiều; nó thực sự trông rất giống nhân viên bán hàng du lịch. Đối với n biến như vậy, bạn đang làm việc với một n không gian ba chiều, vì vậy đối với bất kỳ chương trình thực tế, nhiệm vụ là hoàn toàn untractable.

Tồi tệ hơn: đối với những thứ nghiêm trọng, bạn không chỉ có một số biến số nguyên thủy cố định mà còn tạo ra các biến số trong các lệnh gọi hàm hoặc có các biến có kích thước biến ... hoặc bất cứ thứ gì tương tự, bằng ngôn ngữ hoàn chỉnh Turing. Điều đó làm cho không gian nhà nước trở nên vô tận, phá tan mọi hy vọng về phạm vi bảo hiểm đầy đủ, thậm chí còn được cung cấp thiết bị thử nghiệm mạnh mẽ vô lý.


Điều đó nói rằng ... thực sự mọi thứ không quá ảm đạm. Nó thể proove toàn bộ chương trình là đúng, nhưng bạn sẽ phải từ bỏ một vài ý tưởng.

Đầu tiên: rất nên chuyển sang một ngôn ngữ khai báo. Vì một số lý do, ngôn ngữ bắt buộc luôn luôn trở nên phổ biến nhất, nhưng cách chúng kết hợp các thuật toán với các tương tác trong thế giới thực khiến cho việc nói những gì bạn muốn nói là đúng khó khăn .

Dễ dàng hơn nhiều trong các ngôn ngữ lập trình chức năng thuần túy : chúng có sự phân biệt rõ ràng giữa các tính chất thú vị thực sự của các hàm toán học và các tương tác trong thế giới thực mờ mà bạn không thể thực sự nói gì. Đối với các hàm, rất dễ dàng chỉ định hành vi đúng chính xác, nếu: đối với tất cả các đầu vào có thể (từ các loại đối số), kết quả mong muốn tương ứng xuất hiện, thì hàm sẽ hoạt động chính xác.

Bây giờ, bạn nói rằng điều đó vẫn còn khó hiểu ... xét cho cùng, không gian của tất cả các đối số có thể nói chung cũng là vô hạn. Đúng - mặc dù đối với một chức năng duy nhất, ngay cả thử nghiệm bảo hiểm ngây thơ dẫn bạn đi xa hơn bạn có thể hy vọng trong một chương trình bắt buộc! Tuy nhiên, có một công cụ mạnh mẽ đáng kinh ngạc làm thay đổi trò chơi: định lượng phổ / đa hình tham số . Về cơ bản, điều này cho phép bạn viết các hàm trên các loại dữ liệu rất chung chung, với đảm bảo rằng nếu nó hoạt động với một ví dụ đơn giản về dữ liệu, nó sẽ hoạt động cho mọi đầu vào có thể.

Ít nhất là về mặt lý thuyết. Thật không dễ để tìm đúng loại thực sự quá chung chung đến nỗi bạn hoàn toàn có thể đưa ra điều này - thông thường, bạn cần một ngôn ngữ được gõ phụ thuộc và chúng có xu hướng khá khó sử dụng. Nhưng viết theo kiểu chức năng chỉ với đa hình tham số đã tăng mức độ bảo mật của bạn rất cao - bạn không nhất thiết phải tìm thấy tất cả các lỗi, nhưng bạn sẽ phải che giấu chúng khá tốt để trình biên dịch không phát hiện ra chúng!


Tôi không đồng ý với câu đầu tiên của bạn. Đi qua mọi trạng thái của chương trình, bản thân nó không phát hiện ra bất kỳ lỗi nào . Ngay cả khi bạn kiểm tra sự cố và lỗi rõ ràng, bạn vẫn chưa kiểm tra chức năng thực tế theo bất kỳ cách nào, vì vậy bạn chỉ bao phủ một phần nhỏ của không gian lỗi.
Matthew Đọc

@MatthewRead: nếu bạn áp dụng điều này do đó, thì không gian lỗi Lỗi là một không gian con thích hợp của không gian của tất cả các trạng thái. Tất nhiên, đó chỉ là giả thuyết bởi vì ngay cả các quốc gia chính xác của NỀN đã tạo ra một không gian quá rộng lớn để cho phép mọi thử nghiệm toàn diện.
leftaroundabout
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.