Skip to content

Commit

Permalink
Merge branch 'ab/tap'
Browse files Browse the repository at this point in the history
* ab/tap:
  t/README: document more test helpers
  t/README: proposed rewording...
  t/README: Document the do's and don'ts of tests
  t/README: Add a section about skipping tests
  t/README: Document test_expect_code
  t/README: Document test_external*
  t/README: Document the prereq functions, and 3-arg test_*
  t/README: Typo: paralell -> parallel
  t/README: The trash is in 't/trash directory.$name'
  t/t9700/test.pl: don't access private object members, use public access methods
  t9700: Use Test::More->builder, not $Test::Builder::Test
  tests: Say "pass" rather than "ok" on empty lines for TAP
  tests: Skip tests in a way that makes sense under TAP
  test-lib: output a newline before "ok" under a TAP harness
  test-lib: Make the test_external_* functions TAP-aware
  test-lib: Adjust output to be valid TAP format
  • Loading branch information
gitster committed Jul 7, 2010
2 parents fcd91f8 + c966745 commit 2a16315
Show file tree
Hide file tree
Showing 46 changed files with 369 additions and 111 deletions.
253 changes: 229 additions & 24 deletions t/README
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,48 @@ The easiest way to run tests is to say "make". This runs all
the tests.

*** t0000-basic.sh ***
* ok 1: .git/objects should be empty after git-init in an empty repo.
* ok 2: .git/objects should have 256 subdirectories.
* ok 3: git-update-index without --add should fail adding.
ok 1 - .git/objects should be empty after git init in an empty repo.
ok 2 - .git/objects should have 3 subdirectories.
ok 3 - success is reported like this
...
* ok 23: no diff after checkout and git-update-index --refresh.
* passed all 23 test(s)
*** t0100-environment-names.sh ***
* ok 1: using old names should issue warnings.
* ok 2: using old names but having new names should not issue warnings.
...

Or you can run each test individually from command line, like
this:

$ sh ./t3001-ls-files-killed.sh
* ok 1: git-update-index --add to add various paths.
* ok 2: git-ls-files -k to show killed files.
* ok 3: validate git-ls-files -k output.
* passed all 3 test(s)
ok 43 - very long name in the index handled sanely
# fixed 1 known breakage(s)
# still have 1 known breakage(s)
# passed all remaining 42 test(s)
1..43
*** t0001-init.sh ***
ok 1 - plain
ok 2 - plain with GIT_WORK_TREE
ok 3 - plain bare

Since the tests all output TAP (see http://testanything.org) they can
be run with any TAP harness. Here's an example of parallel testing
powered by a recent version of prove(1):

$ prove --timer --jobs 15 ./t[0-9]*.sh
[19:17:33] ./t0005-signals.sh ................................... ok 36 ms
[19:17:33] ./t0022-crlf-rename.sh ............................... ok 69 ms
[19:17:33] ./t0024-crlf-archive.sh .............................. ok 154 ms
[19:17:33] ./t0004-unwritable.sh ................................ ok 289 ms
[19:17:33] ./t0002-gitfile.sh ................................... ok 480 ms
===( 102;0 25/? 6/? 5/? 16/? 1/? 4/? 2/? 1/? 3/? 1... )===

prove and other harnesses come with a lot of useful options. The
--state option in particular is very useful:

# Repeat until no more failures
$ prove -j 15 --state=failed,save ./t[0-9]*.sh

You can also run each test individually from command line, like this:

$ sh ./t3010-ls-files-killed-modified.sh
ok 1 - git update-index --add to add various paths.
ok 2 - git ls-files -k to show killed files.
ok 3 - validate git ls-files -k output.
ok 4 - git ls-files -m to show modified files.
ok 5 - validate git ls-files -m output.
# passed all 5 test(s)
1..5

You can pass --verbose (or -v), --debug (or -d), and --immediate
(or -i) command line argument to the test, or by setting GIT_TEST_OPTS
Expand Down Expand Up @@ -198,15 +221,101 @@ This test harness library does the following things:
- If the script is invoked with command line argument --help
(or -h), it shows the test_description and exits.

- Creates an empty test directory with an empty .git/objects
database and chdir(2) into it. This directory is 't/trash directory'
if you must know, but I do not think you care.
- Creates an empty test directory with an empty .git/objects database
and chdir(2) into it. This directory is 't/trash
directory.$test_name_without_dotsh', with t/ subject to change by
the --root option documented above.

- Defines standard test helper functions for your scripts to
use. These functions are designed to make all scripts behave
consistently when command line arguments --verbose (or -v),
--debug (or -d), and --immediate (or -i) is given.

Do's, don'ts & things to keep in mind
-------------------------------------

Here are a few examples of things you probably should and shouldn't do
when writing tests.

Do:

- Put all code inside test_expect_success and other assertions.

Even code that isn't a test per se, but merely some setup code
should be inside a test assertion.

- Chain your test assertions

Write test code like this:

git merge foo &&
git push bar &&
test ...

Instead of:

git merge hla
git push gh
test ...

That way all of the commands in your tests will succeed or fail. If
you must ignore the return value of something (e.g. the return
value of export is unportable) it's best to indicate so explicitly
with a semicolon:

export HLAGH;
git merge hla &&
git push gh &&
test ...

Don't:

- exit() within a <script> part.

The harness will catch this as a programming error of the test.
Use test_done instead if you need to stop the tests early (see
"Skipping tests" below).

- Break the TAP output

The raw output from your test may be interpreted by a TAP harness. TAP
harnesses will ignore everything they don't know about, but don't step
on their toes in these areas:

- Don't print lines like "$x..$y" where $x and $y are integers.

- Don't print lines that begin with "ok" or "not ok".

TAP harnesses expect a line that begins with either "ok" and "not
ok" to signal a test passed or failed (and our harness already
produces such lines), so your script shouldn't emit such lines to
their output.

You can glean some further possible issues from the TAP grammar
(see http://search.cpan.org/perldoc?TAP::Parser::Grammar#TAP_Grammar)
but the best indication is to just run the tests with prove(1),
it'll complain if anything is amiss.

Keep in mind:

- Inside <script> part, the standard output and standard error
streams are discarded, and the test harness only reports "ok" or
"not ok" to the end user running the tests. Under --verbose, they
are shown to help debugging the tests.


Skipping tests
--------------

If you need to skip all the remaining tests you should set skip_all
and immediately call test_done. The string you give to skip_all will
be used as an explanation for why the test was skipped. for instance:

if ! test_have_prereq PERL
then
skip_all='skipping perl interface tests, perl not available'
test_done
fi

End with test_done
------------------
Expand All @@ -222,9 +331,9 @@ Test harness library
There are a handful helper functions defined in the test harness
library for your script to use.

- test_expect_success <message> <script>
- test_expect_success [<prereq>] <message> <script>

This takes two strings as parameter, and evaluates the
Usually takes two strings as parameter, and evaluates the
<script>. If it yields success, test is considered
successful. <message> should state what it is testing.

Expand All @@ -234,7 +343,14 @@ library for your script to use.
'git-write-tree should be able to write an empty tree.' \
'tree=$(git-write-tree)'

- test_expect_failure <message> <script>
If you supply three parameters the first will be taken to be a
prerequisite, see the test_set_prereq and test_have_prereq
documentation below:

test_expect_success TTY 'git --paginate rev-list uses a pager' \
' ... '

- test_expect_failure [<prereq>] <message> <script>

This is NOT the opposite of test_expect_success, but is used
to mark a test that demonstrates a known breakage. Unlike
Expand All @@ -243,6 +359,16 @@ library for your script to use.
success and "still broken" on failure. Failures from these
tests won't cause -i (immediate) to stop.

Like test_expect_success this function can optionally use a three
argument invocation with a prerequisite as the first argument.

- test_expect_code [<prereq>] <code> <message> <script>

Analogous to test_expect_success, but pass the test if it exits
with a given exit <code>

test_expect_code 1 'Merge with d/f conflicts' 'git merge "merge msg" B master'

- test_debug <script>

This takes a single argument, <script>, and evaluates it only
Expand Down Expand Up @@ -275,6 +401,85 @@ library for your script to use.
Merges the given rev using the given message. Like test_commit,
creates a tag and calls test_tick before committing.

- test_set_prereq SOME_PREREQ

Set a test prerequisite to be used later with test_have_prereq. The
test-lib will set some prerequisites for you, e.g. PERL and PYTHON
which are derived from ./GIT-BUILD-OPTIONS (grep test_set_prereq
test-lib.sh for more). Others you can set yourself and use later
with either test_have_prereq directly, or the three argument
invocation of test_expect_success and test_expect_failure.

- test_have_prereq SOME PREREQ

Check if we have a prerequisite previously set with
test_set_prereq. The most common use of this directly is to skip
all the tests if we don't have some essential prerequisite:

if ! test_have_prereq PERL
then
skip_all='skipping perl interface tests, perl not available'
test_done
fi

- test_external [<prereq>] <message> <external> <script>

Execute a <script> with an <external> interpreter (like perl). This
was added for tests like t9700-perl-git.sh which do most of their
work in an external test script.

test_external \
'GitwebCache::*FileCache*' \
"$PERL_PATH" "$TEST_DIRECTORY"/t9503/test_cache_interface.pl

If the test is outputting its own TAP you should set the
test_external_has_tap variable somewhere before calling the first
test_external* function. See t9700-perl-git.sh for an example.

# The external test will outputs its own plan
test_external_has_tap=1

- test_external_without_stderr [<prereq>] <message> <external> <script>

Like test_external but fail if there's any output on stderr,
instead of checking the exit code.

test_external_without_stderr \
'Perl API' \
"$PERL_PATH" "$TEST_DIRECTORY"/t9700/test.pl

- test_must_fail <git-command>

Run a git command and ensure it fails in a controlled way. Use
this instead of "! <git-command>" to fail when git commands
segfault.

- test_might_fail <git-command>

Similar to test_must_fail, but tolerate success, too. Use this
instead of "<git-command> || :" to catch failures due to segv.

- test_cmp <expected> <actual>

Check whether the content of the <actual> file matches the
<expected> file. This behaves like "cmp" but produces more
helpful output when the test is run with "-v" option.

- test_when_finished <script>

Prepend <script> to a list of commands to run to clean up
at the end of the current test. If some clean-up command
fails, the test will not pass.

Example:

test_expect_success 'branch pointing to non-commit' '
git rev-parse HEAD^{tree} >.git/refs/heads/invalid &&
test_when_finished "git update-ref -d refs/heads/invalid" &&
...
'


Tips for Writing Tests
----------------------

Expand Down
4 changes: 2 additions & 2 deletions t/lib-git-svn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ git_svn_id=git""-svn-id

if test -n "$NO_SVN_TESTS"
then
say 'skipping git svn tests, NO_SVN_TESTS defined'
skip_all='skipping git svn tests, NO_SVN_TESTS defined'
test_done
fi
if ! test_have_prereq PERL; then
say 'skipping git svn tests, perl not available'
skip_all='skipping git svn tests, perl not available'
test_done
fi

Expand Down
3 changes: 1 addition & 2 deletions t/lib-httpd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

if test -z "$GIT_TEST_HTTPD"
then
say "skipping test, network testing disabled by default"
say "(define GIT_TEST_HTTPD to enable)"
skip_all="Network testing disabled (define GIT_TEST_HTTPD to enable)"
test_done
fi

Expand Down
12 changes: 6 additions & 6 deletions t/t1020-subdirectory.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ test_expect_success 'update-index and ls-files' '
cd "$HERE" &&
git update-index --add one &&
case "`git ls-files`" in
one) echo ok one ;;
one) echo pass one ;;
*) echo bad one; exit 1 ;;
esac &&
cd dir &&
git update-index --add two &&
case "`git ls-files`" in
two) echo ok two ;;
two) echo pass two ;;
*) echo bad two; exit 1 ;;
esac &&
cd .. &&
case "`git ls-files`" in
dir/two"$LF"one) echo ok both ;;
dir/two"$LF"one) echo pass both ;;
*) echo bad; exit 1 ;;
esac
'
Expand All @@ -58,17 +58,17 @@ test_expect_success 'diff-files' '
echo a >>one &&
echo d >>dir/two &&
case "`git diff-files --name-only`" in
dir/two"$LF"one) echo ok top ;;
dir/two"$LF"one) echo pass top ;;
*) echo bad top; exit 1 ;;
esac &&
# diff should not omit leading paths
cd dir &&
case "`git diff-files --name-only`" in
dir/two"$LF"one) echo ok subdir ;;
dir/two"$LF"one) echo pass subdir ;;
*) echo bad subdir; exit 1 ;;
esac &&
case "`git diff-files --name-only .`" in
dir/two) echo ok subdir limited ;;
dir/two) echo pass subdir limited ;;
*) echo bad subdir limited; exit 1 ;;
esac
'
Expand Down
9 changes: 6 additions & 3 deletions t/t1304-default-acl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ umask 077
# is a good candidate: exists on all unices, and it has permission
# anyway, so we don't create a security hole running the testsuite.

if ! setfacl -m u:root:rwx .; then
say "Skipping ACL tests: unable to use setfacl"
test_done
setfacl_out="$(setfacl -m u:root:rwx . 2>&1)"
setfacl_ret=$?

if [ $setfacl_ret != 0 ]; then
skip_all="Skipping ACL tests: unable to use setfacl (output: '$setfacl_out'; return code: '$setfacl_ret')"
test_done
fi

check_perms_and_acl () {
Expand Down
Loading

0 comments on commit 2a16315

Please sign in to comment.