2010-08-20 24 views
9

Phương thức sau chỉ được gọi nếu nó đã được xác minh rằng có các chữ số không hợp lệ (bằng cách gọi một phương thức khác). Làm cách nào tôi có thể thử nghiệm bao gồm các dòng throw trong đoạn mã sau? Tôi biết rằng một cách có thể là hợp nhất với nhau VerifyThereAreInvalidiDigits và phương pháp này. Tôi đang tìm bất kỳ ý tưởng nào khác.Làm cách nào để kiểm tra mã không bao giờ được thực thi?

public int FirstInvalidDigitPosition { 
    get { 
     for (int index = 0; index < this.positions.Count; ++index) { 
      if (!this.positions[index].Valid) return index; 
     } 
     throw new InvalidOperationException("Attempt to get invalid digit position whene there are no invalid digits."); 
    } 
} 

Tôi cũng không muốn viết một bài kiểm tra đơn vị rằng các mã bài tập không bao giờ nên được thực thi.

+1

Thực tế là bạn nói rằng nó không nên được thực hiện và không thể liên lạc nói với tôi "Xóa nó". Bạn đã xác thực chuỗi là không hợp lệ để đến đây, vì vậy bạn biết thuộc tính sẽ trả về một cái gì đó. – Michael

Trả lời

22

Nếu "ném" tuyên bố trong câu hỏi thực sự là unreachable dưới bất kỳ kịch bản có thể sau đó nó phải được xóa và thay thế bằng:

Debug.Fail("This should be unreachable; please find and fix the bug that caused this to be reached."); 

Nếu mã có thể truy cập sau đó viết một bài kiểm tra đơn vị đó kiểm tra kịch bản đó. Các kịch bản báo cáo lỗi cho các phương thức có thể truy cập công khai là các kịch bản hoàn toàn hợp lệ. Bạn phải xử lý tất cả các đầu vào một cách chính xác, ngay cả đầu vào xấu. Nếu điều đúng đắn cần làm là ném một ngoại lệ thì hãy kiểm tra xem bạn có đang ném một ngoại lệ hay không.

CẬP NHẬT: theo nhận xét, thực tế là không thể xảy ra lỗi khi truy cập và do đó mã không thể truy cập được. Nhưng bây giờ Debug.Fail không thể truy cập được, và nó không biên dịch vì trình biên dịch ghi chú rằng một phương thức trả về một giá trị có một điểm kết thúc có thể truy cập.

Vấn đề đầu tiên không thực sự là vấn đề; chắc chắn công cụ bảo hiểm mã phải được cấu hình để bỏ qua mã chỉ gỡ lỗi không thể truy cập được. Nhưng cả hai vấn đề có thể được giải quyết bằng cách viết lại vòng lặp:

public int FirstInvalidDigitPosition 
{ 
    get 
    { 
     int index = 0; 
     while(true) 
     { 
      Debug.Assert(index < this.positions.Length, "Attempt to get invalid digit position but there are no invalid digits!"); 
      if (!this.positions[index].Valid) return index; 
      index++; 
     } 
    } 
} 

Một phương pháp khác sẽ được sắp xếp lại mã để bạn không có vấn đề ở nơi đầu tiên:

public int? FirstInvalidDigitPosition { 
    get { 
     for (int index = 0; index < this.positions.Count; ++index) { 
      if (!this.positions[index].Valid) return index; 
     } 
     return null; 
    } 
} 

và bây giờ bạn không cần phải hạn chế người gọi để gọi AreThereInvalidDigits trước; chỉ cần làm cho nó hợp pháp để gọi phương pháp này bất cứ lúc nào. Điều đó có vẻ như là điều an toàn hơn để làm. Các phương pháp phát nổ khi bạn không thực hiện một số kiểm tra tốn kém để xác minh rằng chúng an toàn để gọi là các phương pháp dễ vỡ, nguy hiểm.

+0

Tôi cần phải có đề cập, tôi đang làm TDD, mà tôi không thử nghiệm các trường hợp giả mạo: P Nó là một lớp học công cộng, nhưng phương pháp nội mô-đun. Vì vậy, ném một ngoại lệ không phải là một phần của yêu cầu, do đó không có thử nghiệm. –

+0

Ngoài ra Debug.Fail vẫn sẽ không được mã-bảo hiểm, cũng thay thế ném với Debug.Fail là một lỗi biên dịch. –

+0

@ user93422: Tôi đã cập nhật câu trả lời của mình để giải quyết các điểm của bạn. –

4

Tôi không hiểu tại sao bạn không muốn viết bài kiểm tra đơn vị thực hiện "mã không nên xảy ra".

Nếu "không nên xảy ra", thì tại sao bạn lại viết mã? Bởi vì bạn nghĩ rằng nó có thể xảy ra tất nhiên - có lẽ một lỗi trong việc tái cấu trúc trong tương lai sẽ phá vỡ xác nhận hợp lệ khác của bạn và mã này sẽ được thực hiện.

Nếu bạn nghĩ rằng nó đáng để viết mã, đơn vị đáng thử nghiệm nó.

+0

Tôi đồng ý - viết mã rằng "không bao giờ nên được thực hiện" âm thanh như một bài tập khá lãng phí với tôi. – EnOpenUK

+0

điểm tốt. Tôi viết mã đó vì C# yêu cầu phương thức không có giá trị để kết thúc hoặc trả về hoặc ném. Tôi thà thích ném thời gian ném ngoại lệ vào thời gian chạy. Vì vậy, tôi không phải viết dòng xấu xí đó. Điều này có nghĩa là tôi cần giải pháp cho tính năng ngôn ngữ hoặc tìm lỗi trong thiết kế. –

+1

Để cải thiện thiết kế, tôi muốn sử dụng một phương pháp thay vì một thuộc tính. Thuộc tính "trông" giống như truy cập biến thành viên đơn giản cho người gọi, vì vậy họ có khả năng * ngạc nhiên * nếu mất nhiều thời gian để thực thi, có tác dụng phụ (như thay đổi biến thành viên trong cuộc gọi 'get'), nguyên nhân các sự kiện được kích hoạt hoặc ném một ngoại lệ. Mặt khác, phương pháp trả về giá trị để chỉ ra "không tìm thấy" là một điều bình thường (ví dụ: -1, như string.IndexOf) hoặc ném ngoại lệ - vì vậy phương thức là một lựa chọn thiết kế tốt hơn nhiều. –

3

Một phần của mục đích thử nghiệm là kiểm tra cả hai điều nên xảy ra và những thứ mà có thể xảy ra xảy ra.

Nếu bạn có mã nên không bao giờ thực hiện, nhưng thể dưới bên phải (hoặc sai) điều kiện, bạn có thể xác minh rằng các ngoại lệ xảy ra trong điều kiện thích hợp (trong Unit Test Khung MS) bằng cách trang trí thử nghiệm của bạn phương pháp với:

[ExpectedException(typeof(InvalidOperationException))] 
+0

Tôi đang làm TDD, vì vậy tôi không kiểm tra những thứ _can_ nhưng không bao giờ _should_ xảy ra. Trong trường hợp này, ngoại lệ là dấu hiệu của một lỗi trong mã, và KHÔNG phải là một điều kiện đặc biệt. –

+0

Một cách để nghỉ ngơi những gì bạn đã viết là có những điều bạn biết có thể xảy ra nhưng bạn không làm gì cả! Vì tôi không nghĩ rằng bạn muốn rời khỏi chương trình của bạn để mở cho hành vi không xác định, bạn có thể muốn suy nghĩ thông qua chiến lược thử nghiệm và mã hóa của bạn một số chi tiết! Càng nhiều càng tốt, yêu cầu của bạn phải thỏa đáng đối phó với tất cả các yếu tố đầu vào có thể, bao gồm những yếu tố không mong muốn. Viết các bài kiểm tra để xác minh rằng chương trình của bạn đáp ứng các yêu cầu này. –

4

đó là đôi khi cần thiết để viết các đoạn mã ngắn mà không thể thực hiện, chỉ để xoa dịu một trình biên dịch (ví dụ nếu một chức năng mà luôn luôn ném một ngoại lệ, thoát ứng dụng, vv được gọi từ một hàm có nghĩa vụ trả về một giá trị, trình biên dịch có thể nhấn mạnh rằng người gọi bao gồm một "return 0", "Return Nothing ", vv tuyên bố mà không bao giờ có thể thực thi. Tôi sẽ không nghĩ rằng một trong những nên được yêu cầu để kiểm tra như vậy "mã", vì nó có thể là không thể thực hiện nó mà không vi phạm nghiêm trọng các phần khác của hệ thống.

Một câu hỏi thú vị hơn đi kèm với mã mà bộ xử lý không bao giờ có thể thực thi trong các trường hợp bình thường, nhưng tồn tại để giảm thiểu tác hại từ các trường hợp bất thường. Ví dụ: một số ứng dụng quan trọng về an toàn mà tôi đã viết bắt đầu bằng mã giống như (mã ứng dụng thực là mã máy; được đưa ra dưới đây là mã giả)

 
    register = 0 
    test register for zero 
    if non-zero goto dead 
    register = register - 1 
    test register for zero 
    if non-zero goto okay1 
dead: 
    shut everything down 
    goto dead 
okay1: 
    register = register + 1 
    if non-zero goto dead 

Tôi không chắc chắn chính xác bạn sẽ thử nghiệm như thế nào mã đó trong trường hợp lỗi. Mục đích của mã này là để đảm bảo rằng nếu thanh ghi đã bị tĩnh điện hoặc thiệt hại khác, hoặc nếu không hoạt động, hệ thống sẽ tắt một cách an toàn. Không có một số thiết bị rất ưa thích, mặc dù, tôi không có ý tưởng làm thế nào để kiểm tra mã như vậy.

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