Có bất kỳ lý thuyết chính thức / toán học của kiểm thử phần mềm?


12

Googling "lý thuyết kiểm thử phần mềm" dường như chỉ đưa ra các lý thuyết theo nghĩa mềm của từ này; Tôi đã không thể tìm thấy bất cứ điều gì sẽ phân loại thành một lý thuyết theo nghĩa toán học, lý thuyết thông tin hoặc một số lĩnh vực khoa học khác.

Những gì tôi đang tìm kiếm là một cái gì đó chính thức hóa thử nghiệm là gì, các khái niệm được sử dụng, trường hợp thử nghiệm là gì, tính khả thi của thử nghiệm một cái gì đó, tính thực tế của thử nghiệm một cái gì đó, mức độ mà một cái gì đó nên được thử nghiệm, định nghĩa / giải thích chính thức về mã bảo hiểm, vv

CẬP NHẬT: Ngoài ra, tôi không chắc chắn, theo trực giác, về mối liên hệ giữa xác minh chính thức và những gì tôi đã hỏi, nhưng rõ ràng có một số loại kết nối.


1
Kiểm thử phần mềm rất có giá trị (ví dụ như đưa kiểm thử đơn vị vào thực tế) nhưng lý thuyết của nó sẽ luôn có một số lỗ hổng. Hãy xem xét ví dụ cổ điển này: double pihole(double value) { return (value - Math.PI) / (value - Math.PI); }mà tôi đã học được từ giáo viên toán của mình . Mã này có chính xác một lỗ , không thể tự động phát hiện được từ kiểm tra hộp đen. Trong môn Toán không có lỗ như vậy. Trong tính toán, bạn được phép đóng lỗ nếu giới hạn một phía bằng nhau.
rwong

4
Đây có thể là một phần của những gì bạn đang tìm kiếm - en.wikipedia.org/wiki/F
normal_verification

1
Tôi đề nghị thứ hai @ enderland. Không quan trọng cách tiếp cận kiểm tra của bạn nghiêm ngặt đến mức nào; một số lỗi vẫn sẽ lọt qua các vết nứt và khi bạn bao quát nhiều mã hơn với các thử nghiệm của mình, chi phí tìm lỗi mới sẽ tăng lên. Đây có lẽ là lý do tại sao không ai gặp rắc rối trong việc chính thức hóa khái niệm thử nghiệm - một phương pháp "heuristic" hoạt động gần như tốt với ít đào tạo.
Doval

Kể từ khi tôi làm quen với vùng đất xác minh chính thức thông qua các loại phụ thuộc và tôi hoàn toàn có thể đồng ý với @Doval và enderland.
Erik Kaplun

1
@rwong Tôi cho rằng bạn ám chỉ khả năng cả tử số và mẫu số đều bằng không. Một phần vấn đề là do thiết kế xấu của chức năng này. Khi nói về xác minh chính thức toán học, bạn cần soạn các hàm không phải tùy ý mà tuân theo các quy tắc chính thức, dựa trên các loại dữ liệu chính xác. Trong ví dụ này, bạn sẽ phải sử dụng hàm chia (a,b)=>a/b, cần được mở rộng với giá trị tràn, để có thể ghép chính xác.
Dmitri Zaitsev

Câu trả lời:


8

Đối với một cuốn sách khám phá toán học đằng sau kiểm thử phần mềm ... cuốn sách quan trọng cần có là Nghệ thuật phân tích hiệu suất hệ thống máy tính: Kỹ thuật thiết kế thử nghiệm, đo lường, mô phỏng và mô hình hóa

Mặc dù lần đầu tiên được xuất bản vào năm 1991, nó vẫn còn phổ biến cho đến ngày nay bởi vì đây là một cuốn sách toán học ứng dụng chỉ tập trung vào phân tích hiệu suất, mô phỏng và đo lường.


5

Tôi không thể chỉ ra một nguồn tài nguyên trực tuyến tốt (các bài viết Wikipedia tiếng Anh về các chủ đề này có xu hướng có thể ứng biến được), nhưng tôi có thể tóm tắt một bài giảng mà tôi đã nghe cũng bao gồm lý thuyết kiểm tra cơ bản.

Chế độ kiểm tra

Có các lớp kiểm tra khác nhau, như kiểm tra đơn vị hoặc kiểm tra tích hợp . Một thử nghiệm đơn vị khẳng định rằng một đoạn mã kết hợp (hàm, lớp, mô-đun) được thực hiện theo cách riêng của nó như mong đợi, trong khi thử nghiệm tích hợp khẳng định rằng nhiều đoạn như vậy hoạt động chính xác với nhau.

Một trường hợp thử nghiệm là một môi trường đã biết trong đó một đoạn mã được thực thi, ví dụ bằng cách sử dụng đầu vào thử nghiệm cụ thể hoặc bằng cách chế nhạo các lớp khác. Hành vi của mã sau đó được so sánh với hành vi dự kiến, ví dụ một giá trị trả về cụ thể.

Một thử nghiệm chỉ có thể chứng minh sự hiện diện của một lỗi, không bao giờ thiếu tất cả các lỗi. Các xét nghiệm đặt một giới hạn trên về tính chính xác của chương trình.

Mã số bảo hiểm

Để xác định số liệu bao phủ mã, mã nguồn có thể được dịch sang biểu đồ luồng điều khiển trong đó mỗi nút chứa một đoạn tuyến tính của mã. Điều khiển luồng giữa các nút này chỉ ở cuối mỗi khối và luôn luôn có điều kiện (nếu có điều kiện, thì nút goto A, nút goto B khác). Biểu đồ có một nút bắt đầu và một nút kết thúc.

  • Với biểu đồ này, phạm vi câu lệnh là tỷ lệ của tất cả các nút được truy cập cho tất cả các nút. Bảo hiểm tuyên bố đầy đủ không đủ để thử nghiệm kỹ lưỡng.
  • Phạm vi chi nhánh là tỷ lệ của tất cả các cạnh được truy cập giữa các nút trong CFG so với tất cả các cạnh. Điều này không đủ kiểm tra các vòng lặp.
  • Độ bao phủ của đường dẫn là tỷ lệ của tất cả các đường dẫn được truy cập cho tất cả các đường dẫn, trong đó một đường dẫn là bất kỳ chuỗi các cạnh nào từ đầu đến cuối nút. Vấn đề là với các vòng lặp, có thể có vô số đường dẫn, do đó, phạm vi bảo hiểm đường dẫn đầy đủ không thể được kiểm tra trên thực tế.

Do đó thường hữu ích để kiểm tra phạm vi điều kiện .

  • Trong phạm vi điều kiện đơn giản , mỗi điều kiện nguyên tử là một lần đúng và một lần sai - nhưng điều này không đảm bảo phạm vi bảo hiểm tuyên bố đầy đủ.
  • Trong phạm vi bao phủ nhiều điều kiện , các điều kiện nguyên tử đã thực hiện trên tất cả các kết hợp truefalse. Điều này ngụ ý bảo hiểm chi nhánh đầy đủ, nhưng khá tốn kém. Chương trình có thể có các ràng buộc bổ sung loại trừ các kết hợp nhất định. Kỹ thuật này là tốt để có được phạm vi bảo hiểm chi nhánh, có thể tìm thấy mã chết, nhưng không thể tìm thấy lỗi xuất phát từ điều kiện sai .
  • Trong phạm vi bảo hiểm nhiều điều kiện tối thiểu , mỗi điều kiện nguyên tử và hỗn hợp là một lần đúng và sai. Nó vẫn ngụ ý bảo hiểm chi nhánh đầy đủ. Nó là một tập hợp con của bảo hiểm nhiều điều kiện, nhưng yêu cầu ít trường hợp thử nghiệm hơn.

Khi xây dựng đầu vào kiểm tra bằng cách sử dụng phạm vi điều kiện, thì cần tính đến đoản mạch. Ví dụ,

function foo(A, B) {
  if (A && B) x()
  else        y()
}

cần phải được thử nghiệm với foo(false, whatever), foo(true, false)foo(true, true)cho đầy đủ bảo hiểm tình trạng nhiều tối thiểu.

Nếu bạn có các đối tượng có thể ở nhiều trạng thái, thì việc kiểm tra tất cả các chuyển trạng thái tương tự với các luồng điều khiển có vẻ hợp lý.

Có một số số liệu bảo hiểm phức tạp hơn, nhưng chúng thường tương tự như các số liệu được trình bày ở đây.

Đây là các phương pháp thử nghiệm hộp trắng , và có thể được tự động hóa một phần. Lưu ý rằng một bộ kiểm tra đơn vị nên đặt mục tiêu có độ bao phủ mã cao theo bất kỳ số liệu được chọn nào, nhưng 100% không phải lúc nào cũng có thể. Đặc biệt khó kiểm tra xử lý ngoại lệ, trong đó các lỗi phải được đưa vào các vị trí cụ thể.

Kiểm tra chức năng

Sau đó, có các kiểm tra chức năng xác nhận rằng mã tuân thủ thông số kỹ thuật bằng cách xem việc thực hiện dưới dạng hộp đen. Các bài kiểm tra như vậy rất hữu ích cho các bài kiểm tra đơn vị và kiểm tra tích hợp như nhau. Vì không thể kiểm tra tất cả dữ liệu đầu vào có thể (ví dụ: kiểm tra độ dài chuỗi với tất cả các chuỗi có thể), nên rất hữu ích khi nhóm đầu vào (và đầu ra) thành các lớp tương đương - nếu length("foo")đúng, foo("bar")cũng có khả năng hoạt động tốt. Đối với mỗi sự kết hợp có thể có giữa các lớp tương đương đầu vào và đầu ra, ít nhất một đầu vào đại diện được chọn và kiểm tra.

Một bài kiểm tra bổ sung

  • trường hợp cạnh length(""), foo("x"), length(longer_than_INT_MAX),
  • các giá trị được cho phép bởi ngôn ngữ, nhưng không phải bởi hợp đồng của chức năng length(null)
  • các dữ liệu rác càng tốt length("null byte in \x00 the middle")...

Với số, điều này có nghĩa là thử nghiệm 0, ±1, ±x, MAX, MIN, ±∞, NaNvà với phép so sánh dấu phẩy động kiểm tra hai phao lân cận. Ngoài ra, các giá trị thử nghiệm ngẫu nhiên có thể được chọn từ các lớp tương đương. Để dễ dàng gỡ lỗi, cần ghi lại hạt giống được sử dụng

Kiểm tra phi chức năng: Kiểm tra tải trọng, kiểm tra căng thẳng

Một phần mềm có các yêu cầu phi chức năng, cũng phải được kiểm tra. Chúng bao gồm kiểm tra tại các ranh giới xác định (kiểm tra tải) và vượt ra ngoài chúng (kiểm tra căng thẳng). Đối với một trò chơi trên máy tính, điều này có thể khẳng định số lượng khung hình tối thiểu mỗi giây trong một thử nghiệm tải. Một trang web có thể được kiểm tra căng thẳng để quan sát thời gian phản hồi khi số lượng khách truy cập dự kiến ​​gấp đôi so với các máy chủ. Các thử nghiệm như vậy không chỉ phù hợp với toàn bộ hệ thống mà còn cho các thực thể đơn lẻ - làm thế nào để một bảng băm xuống cấp với một triệu mục?

Các loại thử nghiệm khác là thử nghiệm toàn hệ thống trong đó các kịch bản được mô phỏng hoặc thử nghiệm chấp nhận để chứng minh rằng hợp đồng phát triển đã được thực hiện.

Phương pháp không thử nghiệm

Nhận xét

Có những kỹ thuật không thử nghiệm có thể được sử dụng để đảm bảo chất lượng. Ví dụ là các hướng dẫn, đánh giá mã chính thức hoặc lập trình cặp. Mặc dù một số bộ phận có thể được tự động hóa (ví dụ: bằng cách sử dụng linters), nhưng những thứ này thường tốn nhiều thời gian. Tuy nhiên, đánh giá mã bởi các lập trình viên có kinh nghiệm có tỷ lệ phát hiện lỗi cao và đặc biệt có giá trị trong quá trình thiết kế, nơi không thể kiểm tra tự động.

Khi đánh giá mã rất tuyệt vời, tại sao chúng ta vẫn viết bài kiểm tra? Ưu điểm lớn của các bộ kiểm thử là chúng có thể chạy (phần lớn) tự động và rất hữu ích cho các bài kiểm tra hồi quy .

Xác minh chính thức

Xác minh chính thức đi và chứng minh các thuộc tính nhất định của mã. Xác minh thủ công chủ yếu là khả thi cho các phần quan trọng, ít hơn cho toàn bộ chương trình. Bằng chứng đặt một giới hạn thấp hơn về tính đúng đắn của chương trình. Bằng chứng có thể được tự động hóa ở một mức độ nhất định, ví dụ thông qua trình kiểm tra kiểu tĩnh.

Một số bất biến có thể được kiểm tra rõ ràng bằng cách sử dụng các assertcâu lệnh.


Tất cả các kỹ thuật này có vị trí của chúng, và là bổ sung. TDD viết các bài kiểm tra chức năng lên phía trước, nhưng các bài kiểm tra có thể được đánh giá bằng các số liệu bảo hiểm của chúng sau khi mã được thực thi.

Viết mã kiểm tra có nghĩa là viết các đơn vị mã nhỏ có thể được kiểm tra riêng (các hàm trợ giúp với độ chi tiết phù hợp, nguyên tắc trách nhiệm duy nhất). Càng ít đối số, mỗi hàm càng tốt. Mã như vậy cũng cho vay để chèn các đối tượng giả, ví dụ như thông qua tiêm phụ thuộc.


2
Tôi đánh giá cao câu trả lời phức tạp, nhưng tôi sợ nó đã gần như không có gì để làm với những gì tôi hỏi :) Nhưng, may mắn, programmers.stackexchange.com/questions/78675/... có vẻ là càng gần như nó được với những gì tôi đã nhằm vào.
Erik Kaplun

Đây là công cụ tuyệt vời. Bạn có thể giới thiệu bất kỳ cuốn sách hoặc những thứ?
Marcin

4

Có lẽ "kiểm tra dựa trên đặc điểm kỹ thuật" cũng là loại câu trả lời cho câu hỏi của bạn. Kiểm tra các Mô-đun kiểm tra này (mà tôi chưa sử dụng). Họ yêu cầu bạn viết biểu thức toán học để chỉ định các bộ giá trị thử nghiệm, thay vì viết thử nghiệm đơn vị bằng các giá trị dữ liệu đơn được chọn.

Kiểm tra :: Bài giảng

Như tác giả nói, Mô-đun Perl này được lấy cảm hứng từ Mô-đun kiểm tra nhanh của Haskell . Có nhiều liên kết trên trang này, một số trong đó đã chết.


2

Một cách tiếp cận dựa trên toán học là tất cả các thử nghiệm cặp . Ý tưởng là hầu hết các lỗi được kích hoạt bởi một lựa chọn tùy chọn cấu hình duy nhất và hầu hết các phần còn lại được kích hoạt bởi một cặp tùy chọn nhất định được thực hiện đồng thời. Do đó, hầu hết có thể được bắt bằng cách kiểm tra "tất cả các cặp". Một lời giải thích toán học (với sự khái quát hóa) có ở đây:

Hệ thống AETG: một cách tiếp cận để thử nghiệm dựa trên thiết kế tổ hợp

(có nhiều tài liệu tham khảo như vậy)


2

Có một số phương trình toán học được sử dụng, nhưng nó phụ thuộc vào loại kiểm thử phần mềm mà bạn đang sử dụng. Chẳng hạn, Giả định lỗi nghiêm trọng giả định rằng các lỗi không phải là sản phẩm của 2 lỗi trở lên đồng thời. Phương trình sau đây là: f = 4n + 1. f = hàm tính số trường hợp kiểm thử cho một số biến đã cho ( n) + 1 là phép cộng của hằng số trong đó tất cả các biến đều đảm nhận giá trị danh nghĩa.

Một loại thử nghiệm khác yêu cầu các phương trình toán học là Thử nghiệm mạnh mẽ là thử nghiệm tính mạnh mẽ hoặc tính chính xác của các trường hợp thử nghiệm trong một quy trình thử nghiệm. Trong thử nghiệm này, bạn sẽ nhập các biến trong phạm vi đầu vào hợp pháp (các trường hợp thử nghiệm sạch) và các biến đầu vào bên ngoài phạm vi đầu vào (các trường hợp thử nghiệm bẩn). Bạn sẽ sử dụng phương trình toán học sau: f = 6n + 1 . 6n chỉ ra rằng mỗi biến phải giả định 6 giá trị khác nhau trong khi các giá trị khác giả sử giá trị danh nghĩa. * + 1 * đại diện cho việc thêm hằng số 1.

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.