5

Điều gì được coi là phương pháp tốt nhất để kiểm tra đơn vị một đơn vị phức tạp như trình biên dịch?Đơn vị thử nghiệm một trình biên dịch

Tôi đã viết một vài trình biên dịch và thông dịch viên qua nhiều năm và tôi thấy loại mã này khá khó để kiểm tra theo cách tốt.

Nếu chúng ta lấy một cái gì đó như thế hệ Cây cú pháp trừu tượng. làm thế nào bạn sẽ kiểm tra điều này bằng cách sử dụng TDD?

Cấu trúc nhỏ có thể dễ dàng kiểm tra. ví dụ: một cái gì đó dọc theo dòng:

string code = @"public class Foo {}"; 
AST ast = compiler.Parse(code); 

Vì điều đó sẽ không tạo ra nhiều nút ast.

Nhưng nếu tôi thực sự muốn kiểm tra rằng trình biên dịch có thể tạo ra một AST cho một cái gì đó giống như một phương pháp:

[TestMethod] 
public void Can_parse_integer_instance_method_in_class() 
{ 
    string code = @"public class Foo { public int method(){ return 0;}}"; 
    AST ast = compiler.Parse(code); 

Những gì bạn sẽ khẳng định trên? Xác định thủ công AST đại diện cho mã đã cho và xác nhận rằng AST được tạo ra phù hợp với AST được xác định thủ công có vẻ khó chịu và thậm chí có thể bị lỗi.

Vậy các chiến thuật tốt nhất cho TDD'ing các tình huống phức tạp như thế này là gì?

+0

Nó chỉ là một trong rất nhiều ví dụ về lý do tại sao các bài kiểm tra đơn vị là vô ích và kém hơn, và trọng tâm phải được kiểm tra tích hợp. TDD là dành cho CRUD, không phải cho những thứ nghiêm trọng. Đối với các trình biên dịch, thử nghiệm mã được tạo ngẫu nhiên là cách tiếp cận tốt nhất có thể. Ví dụ: http://www.cs.utah.edu/~regehr/papers/pldi11-preprint.pdf –

+0

Bạn cũng có thể quan tâm đến cách tiếp cận vượt trội để xây dựng trình biên dịch an toàn: http://compcert.inria.fr/doc /index.html - đặc tả chính thức chắc chắn là một đảm bảo tốt hơn về chất lượng hơn bất kỳ thử nghiệm có thể nào. –

+0

@peer, bạn đang nói về "phương pháp" nào? Nếu một trình phân tích cú pháp được tạo ra (nghĩ 'bison' và giống nhau), bạn sẽ có một ngữ pháp nguyên khối và một đống mã không thể đọc được. Không có gì để kiểm tra bên cạnh ngữ pháp nói chung. Nếu đó là một trình phân tích cú pháp đệ quy viết tay, thì việc kiểm thử đơn vị thậm chí còn khó hơn (xem mã nguồn Clang và cố gắng nghĩ về cách giả lập ASTContext và luồng đầu vào cho mỗi mục trình phân tích cú pháp nhỏ). Kiểm thử đơn vị thực sự vô nghĩa đối với bất kỳ mã phức tạp nào. –

Trả lời

1

Trước hết phân tích cú pháp thường là một phần tầm thường của dự án trình biên dịch. Theo kinh nghiệm của tôi, không bao giờ mất hơn 10% thời gian (trừ khi chúng ta nói về C++ nhưng bạn sẽ không đặt câu hỏi ở đây nếu bạn thiết kế nó), vì vậy bạn không nên đầu tư nhiều thời gian vào các bài kiểm tra phân tích cú pháp.

Tuy nhiên, TDD (hoặc tuy nhiên bạn gọi nó) có chia sẻ trong việc phát triển trung cấp nơi bạn thường muốn xác minh rằng ví dụ: tối ưu hóa mà bạn vừa thêm vào thực tế đã dẫn đến việc chuyển đổi mã dự kiến. Từ kinh nghiệm của tôi, các thử nghiệm như thế này thường được thực hiện bằng cách đưa ra các trình biên dịch thử nghiệm được chế tạo đặc biệt và lắp ráp đầu ra grepping cho các mẫu mong đợi (vòng lặp này chưa được kiểm tra bốn lần? Chúng ta có quản lý để tránh ghi nhớ là chức năng này không?). Việc lắp ráp tham chiếu không tốt bằng việc phân tích biểu diễn có cấu trúc (S-exprs hoặc XML) nhưng nó rẻ và hoạt động tốt trong hầu hết các trường hợp. Thật khó để hỗ trợ khi trình biên dịch của bạn phát triển.

+0

Tôi đã thực sự sử dụng các biểu thức s trong thử nghiệm trước đây. ví dụ. làm AST của tôi có thể ToString() chính nó thành một biểu thức s .. và sau đó chỉ đơn giản khẳng định rằng kết quả bằng với biểu thức s dự kiến ​​.. hoạt động tốt, tuy nhiên nó cảm thấy hack'ish. hoặc là? –

+0

Vâng, nó là hackish nhưng thường mọi người chọn để sống với điều đó và không đầu tư quá nhiều thời gian vào các bài kiểm tra (không ai yêu thử nghiệm thực sự). Nó có thể giúp chỉ grep cho subexpression và/hoặc cho phép một số khoan dung (đăng ký khác nhau hoặc tên nhãn). – yugr

+0

BTW ở đây là một ví dụ điển hình: [Cơ sở hạ tầng chiếu sáng của LLVM] (http://llvm.org/docs/TestingGuide.html) – yugr

4

Thứ nhất, nếu bạn kiểm tra trình biên dịch, bạn không thể có đủ kiểm tra! Người dùng thực sự dựa vào đầu ra do trình biên dịch tạo ra như thể nó là một tiêu chuẩn luôn vàng, vì vậy thực sự ý thức về chất lượng. Vì vậy, nếu bạn có thể, kiểm tra với mọi bài kiểm tra bạn có thể đưa ra!

Thứ hai, sử dụng tất cả các phương pháp thử nghiệm có sẵn, nhưng sử dụng chúng ở nơi thích hợp. Thật vậy, bạn có thể chứng minh toán học, rằng một sự chuyển đổi nào đó là chính xác. Nếu bạn có thể làm như vậy, bạn nên.

Nhưng mọi trình biên dịch mà tôi đã thấy một số nội bộ liên quan đến chẩn đoán và rất nhiều mã được chế tác thủ công, tối ưu ở nội bộ của nó; do đó các phương pháp chứng minh được hỗ trợ thường không áp dụng được nữa. Ở đây, thử nghiệm được đưa ra, và tôi có ý nghĩa rất nhiều!

Khi thu bài kiểm tra, bạn hãy xem xét trường hợp khác nhau:

  1. Positive Standard-Sự phù hợp: frontend bạn nên chấp nhận mẫu mã nhất định và trình biên dịch phải tạo ra một chương trình chạy một cách chính xác đó.Các thử nghiệm trong thể loại này hoặc cần một trình biên dịch hoặc trình tạo tham chiếu vàng để tạo ra đầu ra chính xác của chương trình thử nghiệm; hoặc nó liên quan đến các chương trình viết tay bao gồm một kiểm tra đối với các giá trị được trang bị bởi lý luận của con người.
  2. Kiểm tra tiêu cực: mọi trình biên dịch phải từ chối mã bị lỗi, như lỗi cú pháp, loại mismatches et cetera. Nó phải tạo ra một số loại thông báo lỗi và cảnh báo nhất định. Tôi không biết bất kỳ phương pháp nào để tự động tạo các thử nghiệm như vậy. Vì vậy, những điều này cần được viết bằng con người.
  3. Kiểm tra chuyển đổi: bất cứ khi nào bạn đưa ra một tối ưu hóa ưa thích trong trình biên dịch của bạn (trung cấp), bạn có thể có một số mã ví dụ trong tâm trí thể hiện tối ưu hóa. Hãy nhận biết các biến đổi trước và sau một mô-đun như vậy, chúng có thể cần các tùy chọn đặc biệt cho trình biên dịch của bạn hoặc trình biên dịch xương trần chỉ với mô-đun được cắm vào đó. Kiểm tra một tập hợp lớn các tổ hợp mô-đun xung quanh hợp lý. Tôi thường kiểm tra hồi quy về biểu diễn trung gian trước và sau khi chuyển đổi cụ thể, xác định tham chiếu bằng cách lập luận chuyên sâu với các đồng nghiệp. Cố gắng viết mã trên cả hai mặt của quá trình chuyển đổi, tức là đoạn mã bạn muốn chuyển đổi và các đoạn mã khác nhau không được.

Bây giờ, điều này nghe có vẻ như rất nhiều công việc! Đúng vậy, nhưng có sự giúp đỡ: có một số bộ thử nghiệm thương mại cho các trình biên dịch (C-) trên thế giới và các chuyên gia có thể giúp bạn áp dụng chúng. Dưới đây là một danh sách nhỏ của những người nổi tiếng với tôi:

+1

Đây là thử nghiệm tích hợp mức cao cao, không phải là công cụ "thử nghiệm đơn vị" kỳ lạ được nhiều người yêu thích bởi các đám hipsters mã hóa web. –

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