testing - serp - seomofo title
Implementando `make check` o` make test` (4)
Haga un script de corredor de prueba que tome un nombre de prueba e infiera el nombre de archivo de entrada, el nombre de archivo de salida y los datos de smaple de eso:
#!/bin/bash
set -e
jscheme < $1.in > $1.out 2>&1
diff -q $1.out $1.cmp
Luego, en tu Makefile
:
TESTS := expr unrecognised
.PHONY: test
test:
for test in $(TESTS); do bash test-runner.sh $$test || exit 1; done
También puedes intentar implementar algo como el marco de prueba simple de automake
.
¿Cómo puedo implementar un marco de prueba de regresión simple con Make? (Estoy usando GNU Make, si eso importa).
Mi makefile actual se ve algo como esto (editado para simplificar):
OBJS = jscheme.o utility.o model.o read.o eval.o print.o
%.o : %.c jscheme.h
gcc -c -o $@ $<
jscheme : $(OBJS)
gcc -o $@ $(OBJS)
.PHONY : clean
clean :
-rm -f jscheme $(OBJS)
Me gustaría tener un conjunto de pruebas de regresión, por ejemplo , expr.in
probar una expresión "buena" y unrecognized.in
expr.cmp
una "mala", con expr.cmp
y unrecognized.cmp
como el resultado esperado para cada una. Las pruebas manuales se verían así:
$ 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
Pensé en agregar un conjunto de reglas al makefile buscando algo como esto:
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]
Mis preguntas:
• ¿Qué pongo en los marcadores de posición [algo]?
• ¿Hay alguna manera de reemplazar el mensaje de diff
con un mensaje que diga “Falló la prueba expr
”?
Lo que acabé con se ve así:
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
Se basa en la idea de Jack Kelly, con la sugerencia de Jonathan Leffler incluida.
Su enfoque original, como se indica en la pregunta, es el mejor. Cada una de sus pruebas tiene la forma de un par de entradas y salidas esperadas. Make es bastante capaz de iterar a través de estos y ejecutar las pruebas; no hay necesidad de usar un shell for
bucle. De hecho, al hacer esto, está perdiendo la oportunidad de ejecutar sus pruebas en paralelo y creando un trabajo adicional para limpiar archivos temporales (que no son necesarios).
Aquí hay una solución (usando bc como ejemplo):
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 $@ failed" && exit 1)
all : test
@echo "Success, all tests passed."
La solución aborda directamente sus preguntas originales:
- Los marcadores de posición que busca son
$<
y$(word 2, $?)
Correspondientes a los requisitos previos%.test-in
y%.test-cmp
respectivamente. Contrariamente a los comentarios de @reinierpost, los archivos temporales no son necesarios. - El mensaje de diff se oculta y se reemplaza con
echo
. - El makefile debe invocarse con
make -k
para ejecutar todas las pruebas independientemente de si una prueba individual falla o tiene éxito. -
make -k all
solo se ejecutará si todas las pruebas tienen éxito.
Evitamos enumerar cada prueba manualmente cuando definimos la variable de all-tests
al aprovechar la convención de nomenclatura de archivos ( *.test-in
) y las funciones de GNU make para los nombres de archivos . Como beneficio adicional, esto significa que la solución se amplía a decenas de miles de pruebas fuera de la caja, ya que la longitud de las variables es unlimited en la unlimited de GNU. Esto es mejor que la solución basada en shell que se caerá una vez que llegue al límite de la línea de comandos del sistema operativo.
Voy a abordar sólo su pregunta acerca de diff. Tu puedes hacer:
diff file1 file2 > /dev/null || echo Test blah blah failed >&2
aunque es posible que desee utilizar cmp en lugar de diff.
En otra nota, puede que le resulte útil seguir adelante y dar el paso y usar automake. Tu Makefile.am (en su totalidad) se verá así:
bin_PROGRAMS = jscheme jscheme_SOURCES = jscheme.c utility.c model.c read.c eval.c print.c jscheme.h TESTS = test-script
y obtendrás una gran cantidad de objetivos realmente buenos gratis, incluido un marco de prueba bastante completo.