Search code examples
makefileexitstatus

Start server, run tests, stop server


I have a Makefile target that looks like the following

integration-test: git-hooks
    java -Djava.library.path=$$(pwd)/test/integration/lib/DynamoDBLocal_lib \
        -Djava.util.logging.config.file=/dev/null \
        -Dorg.eclipse.jetty.LEVEL=WARN \
        -Dlog4j.com.amazonaws.services.dynamodbv2.local.server.LocalDynamoDBServerHandler=OFF \
        -jar $$(pwd)/test/integration/lib/DynamoDBLocal.jar \
        -inMemory \
        -port 8000 &
    sleep 3
    ./node_modules/.bin/mocha --compilers coffee:coffee-script/register \
        --reporter spec \
        test/integration/main.coffee
    ps -ef | grep [D]ynamoDBLocal_lib | awk '{print $$2}' | xargs kill

Here's what I'm doing:

  • the Java command starts a local instance of Amazon's DynamoDB.
  • I give it 3 seconds to start
  • I run my integration tests
  • I kill the database

What I would like is kill the database regardless of the fact that the tests passed or not. To do that I suppose I need the exit status of the test command and return that, both if the tests fails or if they succeeded.

What is happening is that if tests pass the database is correctly killed, if the tests fail it's not.

I've read in the docs that you can prepend a - in front a command to have make ignore it if it produce a non zero exit status, the problem if I do that is that I don't know if the tests failed or not, since $? will always return 0.

What's the usual practice in this scenario? I'm fine in splitting the target in more targets if that solves my issue.

Thank you.


Solution

  • You'll have to run the entire thing in a single shell, which means you'll need to use command separators (e.g., ;) and backslashes to connect the lines. Then you can store the result and exit with it:

    integration-test: git-hooks
            { java -Djava.library.path=$$(pwd)/test/integration/lib/DynamoDBLocal_lib \
                -Djava.util.logging.config.file=/dev/null \
                -Dorg.eclipse.jetty.LEVEL=WARN \
                -Dlog4j.com.amazonaws.services.dynamodbv2.local.server.LocalDynamoDBServerHandler=OFF \
                -jar $$(pwd)/test/integration/lib/DynamoDBLocal.jar \
                -inMemory \
                -port 8000 & }; \
            sleep 3; \
            ./node_modules/.bin/mocha --compilers coffee:coffee-script/register \
                --reporter spec \
                test/integration/main.coffee; \
            r=$$?; \
            ps -ef | grep [D]ynamoDBLocal_lib | awk '{print $$2}' | xargs kill; \
            exit $$r
    

    However, you can actually do even better if you use a single shell, by killing only the exact process you want instead of using ps:

    integration-test: git-hooks
            { java -Djava.library.path=$$(pwd)/test/integration/lib/DynamoDBLocal_lib \
                -Djava.util.logging.config.file=/dev/null \
                -Dorg.eclipse.jetty.LEVEL=WARN \
                -Dlog4j.com.amazonaws.services.dynamodbv2.local.server.LocalDynamoDBServerHandler=OFF \
                -jar $$(pwd)/test/integration/lib/DynamoDBLocal.jar \
                -inMemory \
                -port 8000 & }; \
            pid=$$!; \
            sleep 3; \
            ./node_modules/.bin/mocha --compilers coffee:coffee-script/register \
                --reporter spec \
                test/integration/main.coffee; \
            r=$$?; \
            kill $$pid; \
            exit $$r