2015-10-09 16 views
10

Tôi dự định viết một trình biên dịch đồ chơi nhỏ trong Haskell cho một ngôn ngữ rất đơn giản để củng cố kỹ năng Haskell của tôi và vui chơi thiết kế một ngôn ngữ mới. Tôi vẫn đang suy nghĩ về một số quyết định chung và một trong những điểm mở lớn nhất là làm thế nào tôi sẽ làm các bài kiểm tra tích hợp. Tôi có các yêu cầu sau:Thử nghiệm tích hợp trình biên dịch trong Haskell

  • Nó nên có thể để tạo ra một danh sách ba (đầu vào, chương trình, đầu ra), như vậy mà thử nghiệm hội nhập của tôi chạy trình biên dịch của tôi để biên dịch chương trình, chạy nhị phân tổng hợp, vượt qua đầu vào cho nó và xác minh rằng đầu ra của chạy bằng với đầu ra đã cho.
    • Có thể mở rộng thử nghiệm tích hợp sau này để kiểm tra các tương tác phức tạp hơn với chương trình, ví dụ: rằng nó thay đổi một tập tin hoặc ngủ trong ít nhất 20 giây hoặc một cái gì đó như thế.

Tôi cũng có những yêu cầu bắt buộc sau đây:

  • Nó nên được càng nhiều một "kết thúc để kết thúc" càng tốt, tức là nó nên đối xử với các wholencompiler như Blackbox càng nhiều càng tốt và nó không cần phải truy cập vào bên trong của trình biên dịch hoặc bất cứ thứ gì như thế.
  • Tất cả mã phải được viết bằng Haskell.
  • Sẽ thật tuyệt nếu tôi nhận được chức năng khung thử nghiệm điển hình miễn phí, tức là không tự mình triển khai. Ví dụ. một thông báo "THÀNH CÔNG" màu xanh lá cây hoặc một tập hợp các thông báo lỗi mô tả lỗi.

Tôi đã cố gắng tìm một cái gì đó đáp ứng nhu cầu của mình, nhưng tôi đã không thành công cho đến nay. Các lựa chọn thay thế mà tôi cho là như sau:

  • shunit sẽ thỏa mãn mọi thứ ngoại trừ điều kiện tôi muốn viết mã trong Haskell.
  • QuickCheck sẽ cho phép tôi viết mọi thứ trong Haskell, nhưng như tôi đã hiểu, có vẻ như nó hầu như chỉ phù hợp với các bài kiểm tra liên quan đến chức năng Haskell và kết quả của nó. Vì vậy, tôi sẽ cần phải kiểm tra chức năng trong trình biên dịch và thư giãn yêu cầu "kết thúc để kết thúc" của tôi.
  • Tôi chỉ có thể viết chương trình Haskell khởi động trình biên dịch trong một tiến trình khác, chuyển nó vào chương trình đầu vào và sau đó bắt đầu mã được biên dịch trong một tiến trình khác, chuyển nó vào trong và kiểm tra kết xuất. Tuy nhiên điều này sẽ liên quan đến rất nhiều mã hóa ở bên cạnh tôi trong thực tế để thực hiện tất cả các tính năng mà một trong những được miễn phí khi sử dụng một khuôn khổ thử nghiệm.

Tôi không chắc chắn tùy chọn nào tôi nên chọn và tôi vẫn hy vọng rằng tôi thiếu một giải pháp tốt. Bạn có bất kỳ ý tưởng về cách tôi có thể tạo ra một bài kiểm tra tích hợp đáp ứng tất cả các yêu cầu của tôi?

Trả lời

4

Tôi đang nghĩ đến unsafePerformIO nên được khá an toàn ở đây xem xét các chương trình nên không bao giờ tương tác với bất cứ điều gì các môi trường thử nghiệm/logic phụ thuộc vào, hoặc, nói cách khác, việc xây dựng và thực hiện nên có thể xem như một chức năng trong sạch bối cảnh thử nghiệm trong môi trường bị cô lập, được kiểm soát. Và tôi nghĩ rằng nó thực sự hữu ích để kiểm tra trình biên dịch của bạn trong điều kiện như vậy. Và QuickCheck sau đó sẽ trở thành một tùy chọn ngay cả đối với thử nghiệm hộp đen. Nhưng một số tâm trí rõ ràng hơn có thể chứng minh tôi đã nhầm lẫn.

Vì vậy, giả sử biên dịch của bạn là ai lấy cái gì như:

type Source = String 

compile :: Source -> Program 

và thực hiện chương trình của bạn là

data Report = Report Output TimeTaken OtherStats ... 

execute :: Program -> IO Report 

bạn khá có thể sử dụng một cách an toàn unsafePerformIO để chuyển đổi đó vào

execute' :: Program -> Report -- or perhaps 'executeUnsafe' 
execute' = unsafePerformIO . execute 

và sau đó

compileAndExec :: Source -> Report 
compileAndExec = compile . execute' 

và sử dụng tính năng đó bằng QuickCheck.


execute gọi một tiến trình con, có được một nhị phân thực tế, thực hiện điều đó, vv, - hoặc diễn giải nhị phân (hoặc bytecode) trong bộ nhớ, là tùy thuộc vào bạn.

Nhưng tôi khuyên bạn nên tách mã byte và tạo nhị phân: theo cách này bạn có thể kiểm tra trình biên dịch riêng biệt với trình liên kết/không, dễ dàng hơn và cũng nhận được thông dịch viên trong quá trình.

+1

Ok, cảm ơn rất nhiều, đó thực sự là một khả năng tốt. Tôi đã không sử dụng unsafePerformIO chưa và khi tôi nghe nói về nó, tôi quyết định tránh nó càng nhiều càng tốt, nhưng tôi đoán đây chính xác là một trong những trường hợp nó hữu ích. Các hoạt động là loại tinh khiết, nhưng Haskell không biết điều đó. Và để có được khung QuickCheck để hiểu nó, tôi phải sử dụng nó. Và bên cạnh đó, nỗi sợ của tôi về việc sử dụng unsafePerformIO không nên áp dụng cho mã kiểm tra anyways. – Lykos

+0

_ "nhưng Haskell không biết rằng" _ - chính xác! Tôi thậm chí còn nghĩ đến việc thêm ý tưởng đó vào câu trả lời! Điều tương tự cũng xảy ra với 'unsafeCoerce' - đó là khi bạn _know_ cho một sự kiện nào đó là chính xác nhưng Haskell chính thống dường như không phù hợp với thực tế của bạn trong hệ thống niềm tin của nó. –

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