# Copyright (C) 2001-2006, The Perl Foundation.
# $Id: tests.pod 12839 2006-05-30 14:34:31Z coke $

=head1 NAME

docs/tests.pod - Testing Parrot

=head1 A basic guide to writing and running tests for Parrot

This is quick and dirty pointer to how the Parrot test suite is executed and
to how new tests for Parrot should be written.
The testing system is liable to change in the future, but tests written
following the guidelines below should be easy to port into a new test suite.

=head1 How to test parrot

The easy way to test parrot is running C<make test>. If you have
updated your code recently and tests began failing, go for a C<make
realclean> and recompile parrot before complaining.

If your architecture supports JIT, you can test parrot JIT engine using C<make
testj>. It works just like C<make test>, but uses the JIT engine when possible.

C<make languages-test> runs the test suite for most language implementations
in the languages directory.

=head2 Submitting smoke test results

Parrot has a status page with smoke test results
L<http://smoke.parrotcode.org/smoke/>. You can supply new tests
results by just running C<make smoke>. It will run the same tests as
C<make test> would, but will additionally create a HTML table with the test
results. At the end, it will try to upload the test results to the
smoke server.

It is also possible to run a smoke test on JIT. For that, try running
C<make smokej>.

C<make languages-smoke> does smoke testing for most language implementations
in the languages directory.

=head1 Location of the test files

The parrot test files, the F<*.t> files, can be found in the F<t> directory.
A quick overview over the subdirs in F<t> can be found in F<t/README>. 

The language implementations usually have their test files in F<languages/*/t>.

New tests should be added to an existing F<*.t> file.
If a previously untested feature is tested,
it might also make sense to create a new F<*.t> file.

=head1 How to write a test

The testing framework needs to know how many tests it should expect.  So the
number of planned tests needs to be incremented when adding a new test. This
is done near the top of a test file, in a line that looks like:

  use Parrot::Test tests => 8;

=head2 Parrot Assembler

PASM tests are mostly used for testing ops.  Appropriate test files for basic
ops are F<t/op/*.t>.  Perl Magic Cookies are tested in F<t/pmc/*.t>.  Add the
new test like this:

    pasm_output_is(<<'CODE', <<'OUTPUT', "name for test");
        *** a big chunk of assembler, eg:
        print   1
        print   "\n" # you can even comment it if it's obscure
        end          # don't forget this...!
    CODE
    *** what you expect the output of the chunk to be, eg.
    1
    OUTPUT

=head2 Parrot Intermediate Representation

Writing tests  in B<PIR> is more convenient. This is done with C<pir_output_is> and
friends.

    pir_output_is(<<'CODE',<<'OUT','nothing useful');
        .include 'library/config.pir'

        .sub main :main
            print "hi\n"
        .end
    CODE
    hi
    OUT

=head2 C source tests

C source tests are usually located in F<t/src/*.t>.  A simple test looks like:

    c_output_is(<<'CODE', <<'OUTPUT', "name for test");
    #include <stdio.h>
    #include "parrot/parrot.h"
    #include "parrot/embed.h"

    static opcode_t *the_test(Parrot_Interp, opcode_t *, opcode_t *);

    int main(int argc, char* argv[]) {
        Parrot_Interp interpreter;
        interpreter = Parrot_new(NULL);

        if (!interpreter)
            return 1;

        Parrot_run_native(interpreter, the_test);
        printf("done\n");
    fflush(stdout);
        return 0;
    }

    static opcode_t*
    the_test(Parrot_Interp interpreter,
        opcode_t *cur_op, opcode_t *start)
    {
        /* Your test goes here. */

        return NULL;  /* always return NULL */
    }
    CODE
    # Anything that might be output prior to "done".
    done
    OUTPUT

Note that it's always a good idea to output "done" to confirm that the compiled
code executed completely. When mixing C<printf> and C<PIO_printf> always append
a C<fflush(stdout);> after the former.

=head2 Test Perl5 helpers

Perl5 unit tests are in F<t/perl/*.t>.

=head2 Testing language implementations

Language implementations are usually tested with 
C<language_output_is> and friends..

=head1 Ideal tests:

=over 4

=item *

Probe the boundaries (including edge cases, errors thrown etc.) of whatever
code they're testing.  These should include potentially out of band input
unless we decide that compilers should check for this themselves.

=item *

Are small and self contained, so that if the tested feature breaks we can
identify where and why quickly.

=item *

Are valid. Essentially, they should conform to the additional documentation
that accompanies the feature (if any). [If there isn't any documentation, then
feel free to add some and/or complain to the mailing list].

=item *

Are a chunk of assembler and a chunk of expected output.

=back

=head1 TODO tests

In test driven development, tests are implemented first.  So the tests are
initially expected to fail.  This can be expressed by marking the tests as
TODO. See L<Test::More> on how to do that.

=head1 SKIP tests

TODO test actually executed, so that unexpected success can be detected.
In the case of missing requirements and in the case of serious breakdowns
the execution of tests can be skipped.
See L<Test::More> on how to do that.

=head1 SEE ALSO

L<http://qa.perl.org/>
F<t/TESTS.STATUS.pod>
F<t/README>

=cut
