2012-02-27 24 views
8

Tôi đang viết một ứng dụng đa luồng và đang cố gắng tìm ra cách viết các bài kiểm tra đơn vị cho nó. Tôi nghĩ đó có lẽ là một câu hỏi khác về cách tốt nhất để làm điều đó. Nhưng dù sao tôi có một lớp như dưới đây biết nó không đề an toàn và muốn chứng minh điều đó trong một thử nghiệm đơn vị nhưng không thể làm việc ra làm thế nào để làm điều đó:Xác định an toàn chủ đề trong các bài kiểm tra đơn vị

public class MyClass 
{ 
    private List<string> MyList = new List<string>(); 

    public void Add(string Data) 
    { 
     MyList.Add(Data); //This is not thread safe!! 
    } 
} 
+5

Nguyên tắc chung là bạn không thể sử dụng kiểm tra đơn vị để ** chứng minh ** mã đó an toàn chỉ hoặc không an toàn. –

+0

@DavidHeffernan Ummmm ..... help! – Jon

+0

Chủ yếu là bạn phải thực hiện loại xác minh này bằng cách lý luận về mã.Các loại thử nghiệm mà Marc mô tả rất hữu ích và mang lại nhiều lợi ích. Nhưng họ không đủ chứng minh điều gì. –

Trả lời

11

Chứng minh rằng vấn đề là an toàn chỉ là khó khăn - có thể là vấn đề khó giải quyết. Bạn có thể chỉ ra rằng một điều kiện chủng tộc rất dễ sản xuất, hoặc khó sản xuất. Nhưng không sản xuất một điều kiện chủng tộc không có nghĩa là nó không có ở đó.

Nhưng: cách tiếp cận thông thường của tôi ở đây (nếu tôi có lý do để suy nghĩ một chút mã nên an toàn chỉ, không phải) là xoay vòng nhiều luồng chờ đợi một ManualResetEvent duy nhất. Chủ đề cuối cùng để đến cổng (sử dụng khóa liên động để đếm) có trách nhiệm mở cổng để tất cả các chuỗi truy cập vào hệ thống cùng một lúc (và đã tồn tại). Sau đó, họ thực hiện công việc và kiểm tra các điều kiện thoát hiểm sane. Sau đó, tôi lặp lại quá trình này một số lượng lớn lần. Điều này thường đủ để tái tạo một chuỗi chủ đề bị nghi ngờ và cho thấy rằng nó di chuyển từ "rõ ràng bị hỏng" sang "không bị hỏng theo cách hiển nhiên" (điều này khác biệt đáng kể với "không bị hỏng").

Cũng lưu ý: hầu hết mã không phải là chủ đề an toàn.

+0

Cảm ơn nhưng tôi viết rất nhiều mã dựa trên luồng và đang cố gắng để nhóm dev chấp nhận đơn vị thử nghiệm/TDD để công cụ của chúng tôi không phải là chủ đề an toàn. – Jon

+0

@Mark bạn có sẵn mã demo không? – Jon

+0

Marc, những gì bạn viết có vẻ rất thú vị, nhưng tiếc là nó không rõ ràng lắm. Bạn có muốn mô tả quá trình của bạn trong một số chi tiết hơn và có thể thêm sự rõ ràng cho một số điểm như 'chủ đề cuối cùng để đến cổng (sử dụng khóa liên động để đếm)' và 'mở cổng'? –

4

an toàn Chủ đề không phải là điều bạn đáng tin cậy có thể kiểm tra bởi vì nó bản chất nó là không xác định. Bạn có thể thử chạy cùng một thao tác vài trăm lần song song trên các luồng khác nhau và xem kết quả có nhất quán ở cuối hay không. Không thực sự tuyệt vời, nhưng tốt hơn là không có gì tôi cho là.

+0

MS Research đã có một Á hậu một lần có thể xác định tất cả các điểm va chạm một cest chúng msotly bằng cách sử dụng một CUSTOM THREAD SCHEDULER trong C#;) Đã được kéo (chờ productization, do đó, không có sẵn tải về từ MS resarch). Vấn đề là bạn cần loại công cụ đó để xác nhận hợp lệ tất cả các kết hợp có thể, một số có thể khó sản xuất bởi vài trăm lần chạy vì chúng chỉ hiếm khi xảy ra. – TomTom

+0

@TomTom Âm thanh thú vị. Nó sẽ là tốt đẹp để xem một cái gì đó như thế trong sản xuất. – spencercw

+0

@spencercw Đồng ý. Tôi nghĩ rằng có một nhu cầu thực sự cho việc này! – Jon

7

Tôi thường xuyên viết các bài kiểm tra đơn vị để chứng minh rằng một số bộ mã là chuỗi an toàn. Thông thường, tôi viết các xét nghiệm này để đáp ứng với một lỗi tìm thấy trong sản xuất. Trong trường hợp này, mục đích của thử nghiệm là chứng minh rằng lỗi được nhân rộng (kiểm tra thất bại), và mã mới sửa vấn đề luồng (kiểm tra), và sau đó hoạt động như một bài kiểm tra hồi quy cho các bản phát hành trong tương lai.

Hầu hết các bài kiểm tra kiểm tra an toàn chủ đề tôi đã viết thử nghiệm một điều kiện chủng tộc thread, nhưng một số cũng kiểm tra cho deadlocks thread.

Kiểm tra đơn vị chủ động mã an toàn chủ đề phức tạp hơn một chút. Không phải vì thử nghiệm đơn vị khó viết hơn, nhưng bởi vì bạn phải phân tích vững chắc để xác định (đoán, thực sự,) những gì có thể là chuỗi không an toàn. Nếu phân tích của bạn là chính xác, thì bạn sẽ có thể viết một bài kiểm tra thất bại cho đến khi bạn làm cho chuỗi mã an toàn.

Khi thử nghiệm cho một điều kiện chủ đề chủng tộc, kiểm tra của tôi hầu như luôn luôn theo cùng một khuôn mẫu: (đây là mã giả)

boolean failed = false; 
int iterations = 100; 

// threads interact with some object - either 
Thread thread1 = new Thread(new ThreadStart(delegate() { 
    for (int i=0; i<iterations; i++) { 
    doSomething(); // call unsafe code 
    // check that object is not out of synch due to other thread 
    if (bad()) { 
     failed = true; 
    } 
    } 
}); 
Thread thread2 = new Thread(new ThreadStart(delegate() { 
    for (int i=0; i<iterations; i++) { 
    doSomething(); // call unsafe code 
    // check that object is not out of synch due to other thread 
    if (bad()) { 
     failed = true; 
    } 
    } 
}); 

thread1.start(); 
thread2.start(); 
thread1.join(); 
thread2.join(); 
Assert.IsFalse(failed, "code was thread safe"); 
+0

Làm thế nào để làm một gia nhập sẽ kiểm tra nó đúng bởi vì không phải là một tham gia chờ đợi cho thread đó là thi hành để kết thúc trước khi một người khác thực hiện? – Jon

+2

@Jon: Khi "start()" được gọi trên cả thread1 và thread2, chúng bắt đầu thực thi. Phép nối() chỉ cho biết luồng chính (chạy thử nghiệm đơn vị), đợi cho đến khi cả hai luồng được thực hiện để kiểm tra kết quả. thread1 và thread2 là những người trong một "cuộc đua", và khi họ từng gọi mã thread không an toàn, sau một số lần lặp lại họ sẽ đặt mã thử nghiệm vào trạng thái xấu một cách đáng tin cậy. Khi join() thoát ra, thread chính có thể kiểm tra xem thử nghiệm đã thành công hay thất bại. –

3

Tôi đã từ bỏ với đơn vị xét nghiệm để thử và phát hiện các vấn đề luồng. Tôi chỉ sử dụng một thử nghiệm tải hệ thống với một bộ phần cứng đầy đủ, (nếu có phần cứng - thường với các công việc của tôi có, uControllers trên mạng), và một số lượng lớn các máy khách tự động không hợp lý chạy phẳng. Tôi để nó chạy trong một tuần trong khi tôi làm những thứ khác. Vào cuối tuần, tôi lấy tải và kiểm tra những gì còn lại. Nếu nó vẫn hoạt động, không có vật thể nào bị rò rỉ và bộ nhớ không tăng đáng kể, tôi sẽ gửi nó.

Chất lượng như tôi có thể đủ khả năng :)

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