2011-02-07 42 views
16

Làm cách nào để triển khai khung kiểm tra hồi quy đơn giản với Make? (Tôi đang sử dụng GNU Make, nếu có vấn đề.)Thực hiện `kiểm tra` hoặc 'thực hiện kiểm tra'

makefile hiện tại của tôi trông giống như sau (thay đổi nội dung vì đơn giản):

OBJS = jscheme.o utility.o model.o read.o eval.o print.o 

%.o : %.c jscheme.h 
    gcc -c -o [email protected] $< 

jscheme : $(OBJS) 
    gcc -o [email protected] $(OBJS) 

.PHONY : clean 

clean : 
    -rm -f jscheme $(OBJS) 

Tôi muốn có một bộ kiểm tra hồi quy, ví dụ, expr.in thử nghiệm một biểu thức "tốt" & unrecognized.in thử nghiệm một "xấu", với expr.cmp & unrecognized.cmp là đầu ra được mong đợi cho mỗi. kiểm tra thủ công sẽ trông như thế này:

$ jscheme <expr.in> expr.out 2>&1 
$ jscheme <unrecognized.in> unrecognized.out 2>&1 
$ diff -q expr.out expr.cmp # identical 
$ diff -q unrecognized.out unrecognized.cmp 
Files unrecognized.out and unrecognized.cmp differ 

Tôi nghĩ để thêm một bộ quy tắc để các makefile tìm kiếm một cái gì đó như thế này:

TESTS = expr.test unrecognized.test 

.PHONY test $(TESTS) 

test : $(TESTS) 

%.test : jscheme %.in %.cmp 
    jscheme <[something.in]> [something.out] 2>&1 
    diff -q [something.out] [something.cmp] 

Câu hỏi của tôi:
• để tôi đặt gì trong [ cái gì đó] giữ chỗ?
• Có cách nào để thay thế tin nhắn từ diff bằng thông báo có nội dung “Kiểm tra expr không thành công” không?

+0

Whence all tempfiles? Điều gì là sai với – reinierpost

+0

@reinierpost: Nếu bạn có cách tốt hơn để thực hiện những so sánh này, bằng mọi cách, hãy đăng câu trả lời bao gồm chúng — đó là _chính xác_ loại trợ giúp mà tôi yêu cầu. –

+0

Xin lỗi, tôi nghĩ tôi đã hủy câu hỏi đó. Bạn cần tempfiles. – reinierpost

Trả lời

8

Cách tiếp cận ban đầu của bạn, như được nêu trong câu hỏi, là tốt nhất. Mỗi bài kiểm tra của bạn ở dạng một cặp đầu vào và đầu ra được mong đợi. Thực hiện khá khả năng lặp qua các bước này và chạy thử nghiệm; không cần sử dụng vòng lặp vỏ for. Trong thực tế, bằng cách làm điều này bạn đang mất cơ hội để chạy thử nghiệm của bạn song song, và tạo thêm công việc cho chính mình để làm sạch các tập tin tạm thời (mà không cần thiết).

Dưới đây là một giải pháp (sử dụng bc là một ví dụ):

SHELL := /bin/bash 

all-tests := $(addsuffix .test, $(basename $(wildcard *.test-in))) 

.PHONY : test all %.test 

BC := /usr/bin/bc 

test : $(all-tests) 

%.test : %.test-in %.test-cmp $(BC) 
    @$(BC) <$< 2>&1 | diff -q $(word 2, $?) - >/dev/null || \ 
    (echo "Test [email protected] failed" && exit 1) 

all : test 
    @echo "Success, all tests passed." 

Giải pháp trực tiếp đề cập đến câu hỏi ban đầu của bạn:

  • Các placeholders bạn đang tìm kiếm là $<$(word 2, $?) tương ứng với điều kiện tiên quyết %.test-in%.test-cmp tương ứng. Trái với các tập tin tạm thời bình luận @reinierpost là không cần thiết.
  • Thông báo khác bị ẩn và được thay thế bằng cách sử dụng echo.
  • Makefile nên được gọi với make -k để chạy tất cả các kiểm tra bất kể thử nghiệm riêng lẻ có thành công hay không.
  • make -k all sẽ chỉ chạy nếu tất cả các thử nghiệm thành công.

Chúng tôi tránh liệt kê mỗi bài kiểm tra bằng tay khi xác định các biến all-tests bằng cách tận dụng các quy ước cách đặt tên tệp (*.test-in) và GNU làm functions for file names. Như một tiền thưởng này có nghĩa là giải pháp quy mô đến hàng chục ngàn bài kiểm tra ra khỏi hộp, như chiều dài của các biến là unlimited trong GNU thực hiện. Điều này là tốt hơn so với giải pháp dựa trên vỏ mà sẽ giảm hơn một khi bạn nhấn hệ điều hành command line limit.

+0

Bạn có thể bao gồm một liên kết đến GNU có liên quan Thực hiện mục nhập thủ công tại ‹[https://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html] (https: //www.gnu .org/software/make/manual/html_node/File-Name-Functions.html) ›? –

+0

Với niềm vui - đã hoàn tất! –

+1

Cảm ơn, tôi đã học được khá nhiều điều bằng cách rút ra GNU làm thủ công và làm việc thông qua ví dụ này! – dpritch

9

Thực hiện một kịch bản thử nghiệm Á hậu mà phải mất một tên thử nghiệm và suy luận tên tập tin đầu vào, đầu ra tên tập tin và dữ liệu smaple từ đó:

#!/bin/bash 
set -e 
jscheme < $1.in > $1.out 2>&1 
diff -q $1.out $1.cmp 

Sau đó, trong bạn Makefile:

TESTS := expr unrecognised 

.PHONY: test 
test: 
    for test in $(TESTS); do bash test-runner.sh $$test || exit 1; done 

Bạn có thể cũng thử triển khai một cái gì đó như automake 's simple test framework.

+1

Tôi thích ý tưởng vòng lặp shell so với kế hoạch ban đầu của các mục tiêu riêng biệt. Kịch bản shell không phải là một ý tưởng tồi, nhưng tôi nghĩ rằng tôi sẽ kết hợp toàn bộ thứ đó vào makefile. –

+1

Ngoài ra tôi là _really_ không tìm cách mở toàn bộ autotools của sâu. –

+1

@jcsalomon: Tôi không có ý sử dụng các autotools, mà là nghiên cứu cách hệ thống thử nghiệm hoạt động. Tôi sẽ để điều này ở đây trong trường hợp bạn đổi ý: http://www.lrde.epita.fr/~adl/autotools.html. Hãy nhớ để thoát khỏi các dấu hiệu '$' trong 'Makefile' của bạn. Nó bắt gặp tôi một vài lần. –

2

Tôi sẽ chỉ giải quyết câu hỏi của bạn về sự khác biệt. Bạn có thể làm:

 
diff file1 file2 > /dev/null || echo Test blah blah failed >&2 

mặc dù bạn có thể muốn sử dụng cmp thay vì khác.

Trên một ghi chú khác, bạn có thể thấy hữu ích khi tiếp tục và sử dụng việc tự động tắt và sử dụng. Makefile.am của bạn (toàn bộ) sẽ trông giống như:

 
bin_PROGRAMS = jscheme 
jscheme_SOURCES = jscheme.c utility.c model.c read.c eval.c print.c jscheme.h 
TESTS = test-script 

và bạn sẽ nhận được rất nhiều toàn bộ các mục tiêu thật sự tốt đẹp miễn phí, bao gồm một khuôn khổ thử nghiệm khá đầy đủ tính năng.

+0

Tôi đã quên mất tính năng vỏ đó; cảm ơn! –

2

Những gì tôi đã kết thúc với vẻ bề ngoài như thế này:

TESTS = whitespace list boolean character \ 
    literal fixnum string symbol quote 

.PHONY: clean test 

test: $(JSCHEME) 
    for t in $(TESTS); do \ 
     $(JSCHEME) < test/$$t.ss > test/$$t.out 2>&1; \ 
     diff test/$$t.out test/$$t.cmp > /dev/null || \ 
      echo Test $$t failed >&2; \ 
    done 

Nó dựa trên ý tưởng Jack Kelly, với tip Jonathan Leffler của bao gồm.

+0

Bạn sẽ muốn có một '|| thoát 1' ở đâu đó trong đó; nếu không bạn chỉ đơn giản là bỏ qua tất cả các thất bại kiểm tra. – l0b0

+0

@ l0b0, tôi cũng không muốn bảo lãnh sau lần thất bại đầu tiên. Cho bạn biết điều gì: bạn tìm ra cách sạch sẽ để thoát khỏi 1' nếu bất kỳ thử nghiệm nào bị lỗi — nhưng sau khi tất cả các thử nghiệm chạy, và tôi sẽ thay đổi câu trả lời được chấp nhận của tôi thành câu trả lời đó. –

+0

'cho ...; chạy thử || error = 1; làm xong; thoát $ error'? – l0b0

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