2009-04-23 72 views
7

Trong các bài kiểm tra đơn vị, tôi đã trở thành được sử dụng để thử nghiệm các phương pháp áp dụng một số giá trị thông thường, một số giá trị vi phạm hợp đồng phương pháp và tất cả các trường hợp biên giới mà tôi có thể đưa ra.Sử dụng ngẫu nhiên và/hoặc lặp lại trong các bài kiểm tra đơn vị?

Nhưng là nó rất xấu thực hành để

  • thử nghiệm trên các giá trị ngẫu nhiên, đây là một giá trị trong một phạm vi bạn nghĩ không bao giờ nên đưa ra bất cứ rắc rối, vì vậy mà mỗi lần chạy thử nghiệm, giá trị khác được truyền trong? Như một loại thử nghiệm mở rộng các giá trị thông thường?
  • kiểm tra trên toàn bộ phạm vi, sử dụng lặp lại?

Tôi có cảm giác cả hai cách tiếp cận này đều không tốt. Với thử nghiệm phạm vi, tôi có thể tưởng tượng rằng nó không thực tế để làm điều đó, kể từ thời điểm nó đang dùng, nhưng với sự ngẫu nhiên?

CẬP NHẬT:

Tôi không tự sử dụng kỹ thuật này, chỉ tự hỏi về nó. Ngẫu nhiên có thể là một công cụ tốt, tôi biết bây giờ, nếu bạn có thể làm cho nó tái tạo khi bạn cần.
Câu trả lời thú vị nhất là 'fuzzing' tip từ Lieven:

http://en.wikipedia.org/wiki/Fuzz_testing

tx

+3

@Peter: Tôi đã sử dụng ngẫu nhiên trong testcases của mình. Nó đã tìm thấy tôi một số lỗi trong SUT và nó đã cho tôi một số lỗi trong testcase của tôi. Cái testcase phức tạp hơn. Bạn sẽ cần một phương pháp để chạy testcase của bạn với các giá trị ngẫu nhiên (s) nó thất bại trên vv ... Tất cả trong tất cả, tôi đang throthling trở lại trên bằng cách sử dụng ngẫu nhiên nhưng không bác bỏ nó enterly. Như với mọi kỹ thuật, nó có giá trị của nó. Bạn nên tra cứu thuật ngữ "fuzzing". –

+1

Lieven, waarom maak je er geen antwoord van? Ik zou het graag accepteren. – Peter

+0

@Peter, trong dat geval ... –

Trả lời

3

Tôi đã sử dụng ngẫu nhiên trong testcases của mình. Nó tìm thấy tôi một số lỗi trong SUT và nó đã cho tôi một số lỗi trong testcase của tôi.

Lưu ý rằng testcase trở nên phức tạp hơn bằng cách sử dụng randomnes.

  • Bạn sẽ cần một phương pháp để chạy testcase của bạn với các giá trị ngẫu nhiên (s) nó không thành công trên
  • Bạn sẽ cần phải đăng nhập các giá trị ngẫu nhiên sử dụng cho tất cả các thử nghiệm.
  • ...

Tất cả trong tất cả, tôi đang cố gắng sử dụng ngẫu nhiên nhưng không loại bỏ nó. Như với mọi kỹ thuật, nó có giá trị của nó.

Đối với một lời giải thích tốt hơn về những gì bạn đang sau, nhìn lên những hạn fuzzing

2

được bạn thử nghiệm gì? Trình tạo số ngẫu nhiên? Hoặc mã của bạn?

Nếu mã của bạn, nếu có lỗi trong mã tạo số ngẫu nhiên thì sao?

Nếu bạn cần tái tạo sự cố, bạn có tiếp tục khởi động lại thử nghiệm với hy vọng rằng cuối cùng nó sẽ sử dụng cùng một trình tự như bạn có khi bạn phát hiện sự cố không?

Nếu bạn quyết định sử dụng trình tạo số ngẫu nhiên để tạo dữ liệu, ít nhất là tạo hạt với giá trị không đổi đã biết, do đó dễ tái tạo.

Nói cách khác, "số ngẫu nhiên" của bạn chỉ là "chuỗi số mà tôi thực sự không quan tâm nhiều đến".

+0

Tôi nghĩ rằng sao chép woul không có vấn đề gì, tôi có thể thấy trong nhật ký số nào đã xúc phạm sự khẳng định, phải không? – Peter

+0

Xác nhận rằng ngắt có thể không cho phép bạn xây dựng lại giá trị đầu vào có vấn đề (ví dụ: khi nó xác nhậnNotNull hoặc assertTrue trên một số giá trị có nguồn gốc) –

+0

Thật vậy, tôi đoán nếu không có giải quyết vấn đề đó, nó có thể loại trừ kỹ thuật này, nhưng có thể có giải pháp đơn giản cho nó tất nhiên là – Peter

5

Kiểm tra đơn vị cần phải nhanh. nếu họ không phải là người sẽ không chạy chúng thường xuyên. Đôi khi tôi đã viết mã để kiểm tra toàn bộ phạm vi nhưng @ Ignore'd đã nhận xét nó ra cuối cùng bởi vì nó thực hiện các bài kiểm tra quá chậm. Nếu tôi sử dụng các giá trị ngẫu nhiên, tôi sẽ tìm một PRNG với các hạt cố định để mỗi lần chạy thực sự kiểm tra cùng một số.

1

Vì vậy, miễn là nó sẽ cho bạn biết một cách nào đó giá trị ngẫu nhiên nó thất bại trên tôi không cho rằng đó là xấu. Tuy nhiên, bạn gần như dựa vào may mắn để tìm ra một vấn đề trong ứng dụng của bạn sau đó.

Kiểm tra toàn bộ phạm vi sẽ đảm bảo bạn có mọi tuyến đường được bao phủ nhưng có vẻ như quá mức khi bạn có các cạnh được bao phủ và, tôi giả định, một vài giá trị được chấp nhận ở mức trung bình.

+2

@Garry, nó không được gọi là may mắn, nó được gọi là fuzzing. –

5
  1. Input ngẫu nhiên - Các xét nghiệm sẽ không được lặp lại (tạo ra kết quả phù hợp mỗi khi họ đang chạy và do đó không được coi là đơn vị xét nghiệm tốt Các xét nghiệm không nên thay đổi suy nghĩ của họ
  2. Phạm vi kiểm tra/RowTests.. - là tốt miễn là họ không làm chậm chạy bộ thử nghiệm ..mỗi thử nghiệm sẽ chạy như nhanh nhất có thể. (Một bộ kiểm tra thực hiện trong 30 giây được chạy thường xuyên hơn một bộ 10 phút) - tốt hơn là 100ms hoặc nhỏ hơn. Điều đó nói rằng Mỗi đầu vào (dữ liệu thử nghiệm) phải là đầu vào 'đại diện'. Nếu tất cả các giá trị đầu vào giống nhau, hãy thử nghiệm mỗi giá trị không thêm bất kỳ giá trị nào và chỉ là việc thu thập số thông thường. Bạn chỉ cần một đại diện từ tập hợp các giá trị đó. Bạn cũng cần đại diện cho các điều kiện biên và các giá trị 'đặc biệt'.

Để biết thêm về chủ trương hoặc thumbrules - xem 'What makes a Good Unit Test?'

Điều đó nói rằng ... những kỹ thuật mà bạn đề cập có thể là tuyệt vời để tìm đầu vào đại diện .. Vì vậy, sử dụng chúng để tìm scenarioX nơi mã thất bại hay thành công không chính xác - sau đó viết một bài kiểm tra đơn vị lặp lại, nhanh chóng, kiểm tra một điều cho kịch bản đó và thêm nó vào bộ thử nghiệm của bạn. Nếu bạn thấy rằng những công cụ này tiếp tục giúp bạn tìm thấy nhiều trường hợp thử nghiệm tốt hơn .. hãy kiên trì với chúng.

Response to rõ OP của:

  • Nếu bạn sử dụng giá trị hạt giống (kiểm tra đầu vào) cho ngẫu nhiên không có máy phát điện của bạn trên mỗi lần chạy kiểm tra, thử nghiệm của bạn không phải là ngẫu nhiên - các giá trị có thể được xác định trước. Tuy nhiên một bài kiểm tra đơn vị lý tưởng không cần bất kỳ đầu vào/đầu ra - đó là lý do tại sao các trường hợp kiểm tra xUnit có dấu hiệu void TC().
  • Nếu bạn sử dụng các giá trị hạt giống khác nhau trên mỗi lần chạy, bây giờ các thử nghiệm của bạn là ngẫu nhiên và không lặp lại được. Tất nhiên bạn có thể truy tìm giá trị hạt giống đặc biệt trong tệp nhật ký của bạn để biết những gì không thành công (và tạo lại lỗi) nhưng tôi thích các thử nghiệm của mình ngay lập tức cho tôi biết những gì không thành công - ví dụ: một Red TestConversionForEnums() cho tôi biết rằng mã Chuyển đổi Enum bị hỏng mà không có bất kỳ sự kiểm tra nào.

Lặp lại - ngụ ý rằng mỗi khi chạy thử nghiệm trên SUT, nó tạo ra kết quả tương tự (vượt qua/thất bại) .. không 'Tôi có thể tạo lại lỗi kiểm tra không?' (Lặp lại! = Reproducible). Để nhắc lại .. loại thử nghiệm khám phá này có thể tốt để xác định nhiều trường hợp kiểm tra hơn nhưng tôi sẽ không thêm điều này vào bộ thử nghiệm mà tôi chạy mỗi khi tôi thực hiện thay đổi mã trong ngày. Tôi muốn khuyên bạn nên làm thử nghiệm thăm dò bằng tay, tìm thấy một số tốt (một số có thể sử dụng tàn bạo) Testers sẽ đi búa và kẹp tại mã của bạn .. sẽ tìm thấy bạn nhiều trường hợp thử nghiệm hơn một máy phát điện đầu vào ngẫu nhiên.

+0

tx cho liên kết – Peter

+0

sẽ không lặp lại được -> có, chúng sẽ, liên kết c trong bài đăng: "dữ liệu thử nghiệm được giữ nguyên. Nếu luồng mờ là số giả ngẫu nhiên, có thể dễ dàng lưu trữ giá trị hạt giống hơn để tái tạo sự cố gắng. " – Peter

+0

Đã thêm câu trả lời làm cập nhật cho câu trả lời của tôi .. vì tôi thích âm thanh bàn phím của tôi :) – Gishu

0

Tôi sẽ không ủng hộ các giá trị hoàn toàn ngẫu nhiên vì nó sẽ cho bạn cảm giác an toàn giả. Nếu bạn không thể đi qua toàn bộ phạm vi (mà thường là trường hợp) nó là hiệu quả hơn nhiều để chọn một tập hợp con bằng tay. Bằng cách này bạn cũng sẽ phải suy nghĩ về các giá trị "lẻ" có thể có, các giá trị làm cho mã chạy khác nhau (và không gần các cạnh).

Bạn có thể sử dụng trình tạo ngẫu nhiên để tạo các giá trị thử nghiệm, kiểm tra xem chúng có đại diện cho một mẫu hay không và sau đó sử dụng chúng. Đây là một ý tưởng tốt, đặc biệt nếu chọn bằng tay sẽ mất quá nhiều thời gian.

Tôi đã sử dụng các giá trị thử nghiệm ngẫu nhiên khi tôi viết trình điều khiển semaphore để sử dụng cho khối hw từ hai chip khác nhau. Trong trường hợp này tôi không thể tìm ra cách chọn các giá trị có ý nghĩa cho timings vì vậy tôi đã ngẫu nhiên hóa tần suất các chip sẽ (độc lập) cố gắng truy cập khối. Nhìn lại nó sẽ vẫn tốt hơn nếu chọn chúng bằng tay, bởi vì để môi trường thử nghiệm hoạt động theo cách mà hai con chip không tự sắp xếp không đơn giản như tôi nghĩ. Đây thực sự là một ví dụ rất hay khi các giá trị ngẫu nhiên không tạo ra một mẫu ngẫu nhiên.

Vấn đề là do thực tế là bất cứ khi nào chip khác đã đặt trước khối khác, chờ đợi và đúng với một semaphore có quyền truy cập ngay sau khi phát hành nó. Khi tôi vạch ra thời gian mà các con chip phải chờ đợi để truy cập các giá trị trong thực tế là rất xa so với ngẫu nhiên. Tồi tệ nhất là khi tôi có cùng một phạm vi giá trị cho cả hai giá trị ngẫu nhiên, nó đã tốt hơn một chút sau khi tôi thay đổi chúng để có các phạm vi khác nhau, nhưng nó vẫn không phải là rất ngẫu nhiên. Tôi bắt đầu nhận được một cái gì đó của một thử nghiệm ngẫu nhiên chỉ sau khi tôi ngẫu nhiên cả hai thời gian chờ đợi giữa các truy cập bao lâu khối đã được dành riêng và chọn bốn bộ cẩn thận.

Cuối cùng tôi có thể đã sử dụng nhiều thời gian hơn để viết mã để sử dụng các giá trị "ngẫu nhiên" so với trước đây tôi đã sử dụng để chọn các giá trị có ý nghĩa bằng tay.

+0

Các giá trị ngẫu nhiên này là bổ sung của khóa học. Tất nhiên các giá trị được chọn đều là giá trị cốt lõi. – Peter

+0

Vấn đề sau đó là những gì sử dụng là những giá trị ngẫu nhiên? Đó là một quan niệm sai lầm phổ biến rằng các trường hợp thử nghiệm nhiều hơn bạn chạy, thì tốt hơn. Điều này không đúng, vì nếu bạn không phân tích các bài kiểm tra của bạn, bạn sẽ chỉ kiểm tra lại các đường dẫn mã giống nhau một lần nữa. Chỉ cần chạy thử nghiệm với các giá trị được xác định trước sẽ cho tôi khá nhiều sự tự tin giống như khi thêm phần tử ngẫu nhiên. – Makis

3

Những gì bạn mô tả thường được gọi là thử nghiệm dựa trên đặc điểm kỹ thuật và đã được triển khai bởi các khung như QuickCheck (Haskell), scalacheck (Scala) và Quviq QuickCheck (Erlang).

Công cụ kiểm tra dựa trên dữ liệu (chẳng hạn như DataProvider trong TestNG) có thể đạt được kết quả tương tự.

Nguyên tắc cơ bản là tạo dữ liệu đầu vào cho chủ thể được thử nghiệm dựa trên một số loại đặc điểm kỹ thuật và cách xa "thực hành không tốt".

+0

+1 cho QuickCheck. Một lợi ích chính của thử nghiệm dựa trên thông số là bạn xác nhận về các thuộc tính quan trọng của dữ liệu và không phải một số giá trị mã hóa ngẫu nhiên khó. –

1

Mục tiêu kiểm tra đơn vị là để có được sự tự tin trong mã của bạn. Do đó, nếu bạn cảm thấy rằng việc sử dụng các giá trị ngẫu nhiên có thể giúp bạn tìm thêm một số lỗi, bạn rõ ràng cần thêm các thử nghiệm để tăng mức độ tin cậy của mình.

Trong trường hợp đó, bạn có thể dựa vào thử nghiệm dựa trên lặp lại để xác định những vấn đề đó. Tôi khuyên bạn nên tạo các thử nghiệm cụ thể mới cho các trường hợp được phát hiện bằng thử nghiệm vòng lặp và xóa các thử nghiệm dựa trên lặp lại rồi; để họ không làm chậm bài kiểm tra của bạn.

+0

Mục đích là tìm lỗi rẻ, không được tự tin. –

1

Tôi đã sử dụng ngẫu nhiên để gỡ lỗi một vấn đề trường với một máy trạng thái bị rò rỉ tài nguyên. Chúng tôi mã kiểm tra, chạy các bài kiểm tra đơn vị và không thể tái tạo rò rỉ.

Chúng tôi đã cho các sự kiện ngẫu nhiên từ toàn bộ không gian sự kiện có thể vào môi trường kiểm tra đơn vị máy trạng thái. Chúng tôi đã xem xét các bất biến sau mỗi sự kiện và dừng lại khi chúng bị vi phạm.

Sự kiện ngẫu nhiên cuối cùng đã phơi bày một chuỗi các sự kiện tạo ra rò rỉ. Máy trạng thái bị rò rỉ tài nguyên khi xảy ra lỗi thứ 2 trong khi khôi phục từ lỗi đầu tiên.

Sau đó chúng tôi có thể tạo lại rò rỉ trong trường.

Vì vậy, ngẫu nhiên tìm thấy một vấn đề khó tìm thấy nếu không. Một chút bạo lực nhưng máy tính không bận tâm vào cuối tuần.

0

công việc Xem David Saff về Theory-Based Testing.

Nói chung tôi muốn tránh sự ngẫu nhiên trong các bài kiểm tra đơn vị, nhưng công cụ lý thuyết là hấp dẫn.

0

Điểm 'chìa khóa' ở đây là kiểm tra đơn vị. Một loạt các giá trị ngẫu nhiên trong phạm vi dự kiến ​​cũng như các cạnh cho trường hợp tốt và phạm vi/ranh giới ouside cho trường hợp xấu có giá trị trong phép thử hồi quy, miễn là hạt giống là hằng số.

kiểm tra đơn vị có thể sử dụng các giá trị ngẫu nhiên trong phạm vi dự kiến, nếu có thể luôn lưu các đầu vào/đầu ra (nếu có) trước và sau.

Các vấn đề liên quan