2010-08-24 25 views
36

Tôi đang sử dụng gcov để đo mức độ phù hợp trong mã C++ của mình. Tôi muốn nhận được mức độ phủ sóng 100%, nhưng bị cản trở bởi thực tế rằng có một số dòng mã không có khả năng lý thuyết (các phương thức được yêu cầu nhưng không bao giờ được gọi, các nhánh mặc định là switch) v.v.) Mỗi nhánh trong số này chứa một tuyên bố assert(false);, nhưng gcov vẫn đánh dấu chúng là un-hit.Làm cách nào để yêu cầu gcov bỏ qua các dòng mã C++ không thể chuyển nhượng được?

Tôi muốn có thể yêu cầu gcov bỏ qua các chi nhánh này. Có cách nào để cung cấp cho gcov thông tin đó - bằng cách chú thích mã nguồn hoặc bằng bất kỳ cơ chế nào khác không?

+0

Điều gì làm cho bạn như vậy chắc chắn rằng dòng là unhittable? Nếu đó là bởi vì bạn đã không thể đánh chúng, tốt đó là những gì bạn đang cố gắng tìm ra với bảo hiểm mã. – doron

+2

@ deus-ex-machina399: Không, không phải vì tôi không thể đánh chúng. Đó là do sự hiểu biết và phân tích mã. Tất nhiên, tôi có thể sai, nhưng tôi không sử dụng phân tích phạm vi mã để cố gắng xác minh sự hiểu biết của tôi về mã nguồn. Tôi đang sử dụng phân tích phạm vi mã để xác minh chất lượng của bộ thử nghiệm của mình. – jchl

+1

@ doron, một ví dụ về mã nên không thể chuyển được là đường dẫn lỗi trong cơ sở hạ tầng thử nghiệm của bạn. Tất nhiên, bạn có thể có thể làm mà không có con đường như vậy, nhưng tôi có chúng. –

Trả lời

35

Vui lòng sử dụng lcov.Nó ẩn phức tạp gcov của, sản xuất đầu ra tốt đẹp, cho phép đầu ra chi tiết cho mỗi thử nghiệm, tính năng lọc dễ dàng tập tin và - ta-TAA - đánh dấu dòng cho dòng đã đánh giá:

Từ geninfo (1):

Sau đây dấu hiệu được công nhận bởi geninfo:

  • LCOV_EXCL_LINE
    • dòng chứa dấu này sẽ được loại trừ.
  • LCOV_EXCL_START
    • đánh dấu sự khởi đầu của một phần loại trừ. Dòng hiện tại là một phần của phần này.
  • LCOV_EXCL_STOP
    • đánh dấu sự kết thúc một phần loại trừ. Dòng hiện tại không phải là một phần của phần này.
+0

Thú vị, tôi đã không nghe nói về lcov. Cảm ơn vì lời giới thiệu! – jchl

+0

Cuối cùng có xung quanh để thử nghiệm này ... và sau khi nâng cấp lên phiên bản lcov> = 1.8, nó hoạt động một sự quyến rũ. Cảm ơn! – jchl

+14

Tôi không phải là người hâm mộ câu trả lời của biểu mẫu "sử dụng một số công cụ khác". Tôi thực sự muốn biết làm thế nào để có được gcov bỏ qua dòng, và không có tùy chọn chuyển sang lcov. Vì vậy, điều này không trả lời câu hỏi. –

0

Tôi không tin điều này là có thể. Gcov phụ thuộc vào gcc để tạo thêm mã để tạo ra mức độ phù hợp. Bản thân GCov chỉ phân tích cú pháp dữ liệu. Điều này có nghĩa là Gcov không thể phân tích mã nào tốt hơn gcc (và tôi giả sử bạn sử dụng -Wall và đã xóa mã được báo cáo là không thể truy cập được). Hãy nhớ rằng các hàm relocatable có thể được gọi từ bất cứ nơi đâu, thậm chí là các dll hay tệp thi hành bên ngoài, do đó không có cách nào trình biên dịch có thể biết chức năng relocatable sẽ không được gọi hoặc những chức năng nào có thể có.

Có thể bạn sẽ cần sử dụng một số công cụ phân tích tĩnh để nhận thông tin mà bạn muốn.

1

Bạn có thể giới thiệu các bài kiểm tra đơn vị về các chức năng liên quan, chỉ tồn tại để đóng gcov bằng cách trực tiếp tấn công các đường dẫn mã không theo luật không? Vì họ là những bài kiểm tra đơn vị, có lẽ họ có thể bỏ qua "điều không thể" của các tình huống. Họ có thể gọi các hàm không bao giờ được gọi, chuyển các giá trị enum không hợp lệ để bắt các nhánh mặc định, v.v.

Sau đó, chạy các kiểm tra đó chỉ trên phiên bản mã của bạn được biên dịch bằng NDEBUG hoặc chạy chúng trong khai thác thử nghiệm rằng khẳng định được kích hoạt - bất kể khung kiểm thử của bạn hỗ trợ.

Tôi thấy nó hơi kỳ quặc mặc dù thông số kỹ thuật cho biết mã phải ở đó, thay vì thông số chứa các yêu cầu chức năng trên mã. Đặc biệt, điều đó có nghĩa là các thử nghiệm của bạn không thử nghiệm các yêu cầu đó, đó là một lý do tốt để giữ các yêu cầu chức năng. Cá nhân tôi muốn sửa đổi các spec để nói, "nếu được gọi với một giá trị enum không hợp lệ, chức năng sẽ thất bại một assert. Người gọi sẽ không gọi hàm với một giá trị enum không hợp lệ trong chế độ phát hành". Hoặc một số như vậy.

Có lẽ những gì nó hiện đang nói, nằm dọc theo dòng "tất cả các câu lệnh chuyển đổi phải có trường hợp mặc định". Nhưng điều đó có nghĩa là các tiêu chuẩn mã hóa đang can thiệp vào hành vi quan sát (ít nhất, có thể quan sát được dưới gcov) bằng cách giới thiệu mã chết. Tiêu chuẩn mã hóa không nên thực hiện điều đó, vì vậy đặc tả chức năng cần tính đến các tiêu chuẩn mã hóa nếu có thể.

Nếu không, bạn có thể quấn mã không thể chuyển được trong #if !GCOV_BUILD và tạo một bản dựng riêng cho lợi ích của gcov. Xây dựng này sẽ thất bại một số yêu cầu, nhưng có điều kiện phân tích mã của bạn là chính xác, nó mang lại cho bạn sự tự tin mà bạn muốn rằng bộ kiểm thử kiểm tra mọi thứ khác.

Chỉnh sửa: bạn nói rằng bạn đang sử dụng trình tạo mã dodgy, nhưng bạn cũng đang yêu cầu giải pháp bằng cách chú thích mã nguồn. Nếu bạn đang thay đổi nguồn, bạn có thể loại bỏ mã chết trong nhiều trường hợp không? Không phải việc thay đổi nguồn được tạo là lý tưởng, nhưng cần phải ...

+0

Nó không phải là "spec" nói rằng các chức năng phải ở đó. Chúng ta có một trình tạo mã tạo các nguyên mẫu cho các hàm, mặc dù chúng không được sử dụng. Một tình huống khác mà đôi khi cây trồng lên là nơi bạn đang thực hiện một giao diện (tức là bắt nguồn từ một lớp với các hàm ảo thuần túy) nhưng chỉ sử dụng một phần của giao diện đó. – jchl

+0

Việc kiểm tra đơn vị gọi các hàm trực tiếp không phải là một ý tưởng tồi, mặc dù phải chạy các thử nghiệm trên bản dựng NDEBUG sẽ gây đau (hiện tại các thử nghiệm đơn vị của chúng tôi chạy trên các bản dựng gỡ lỗi). Nghe có vẻ như nhiều công việc hơn là nó đáng giá. Tôi chỉ có thể loại bỏ các xác nhận, mặc dù tôi thích chúng ở đó vì mục đích tài liệu. Tôi có thể thay thế chúng bằng cách ném một ngoại lệ đặc biệt mà không bao giờ bị bắt ngoại trừ trong bài kiểm tra đơn vị .... đó không phải là một ý tưởng tồi. – jchl

+0

@jchl: "bạn đang triển khai giao diện (nghĩa là xuất phát từ một lớp có chức năng ảo thuần túy) nhưng chỉ sử dụng một phần của giao diện đó". - loại. Tuy nhiên, nếu tôi đã viết các bài kiểm tra toàn diện cho lớp, tôi vẫn sẽ có lớp xác định những gì họ làm, và gọi các chức năng không được sử dụng từ các bài kiểm tra để đảm bảo họ làm điều đó. Và nếu tôi không viết bài kiểm tra toàn diện, tôi sẽ không quan tâm liệu tôi có bảo hiểm mã hay không ;-) –

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