Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions t/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The philosophy of
[Test Driven Design](https://en.wikipedia.org/wiki/Test-driven_development)
is that when a bug is found, a test is written to show it failing
and when it is fixed, the test will pass.
The unit tests are easy to run and amenable to automation. Some services
The unit tests are easy to run and amenable to automation. Some services
can be "mocked" so that behaviour can be tested in their absence.
All of this is to provide confidence that the code does what is intended
and a working test can be better than documentation because it shows how
Expand All @@ -18,8 +18,7 @@ the code currently works in practice.
Old references can be found on the WebWork wiki page
[Unit Testing](https://webwork.maa.org/wiki/Unit_Testing)


# Unit Tests
## Unit Tests

[Unit tests](https://en.wikipedia.org/wiki/Unit_testing) look at small chunks
of self-coherent code to verify the behaviour of a subroutine or module.
Expand Down Expand Up @@ -88,32 +87,30 @@ is check_score($f->eval(x=>2), '4'), 1, 'math objects: eval x^2 at x=2';
The `check_score` subroutine evaluates and compares a MathObject with a string representation of the answer.
If the score is 1, then the two are equal.


# Integration tests
## Integration tests

[Integration testing](https://en.wikipedia.org/wiki/Integration_testing)
tests components working together as a group. The files with the `.pg`
tests components working together as a group. The files with the `.pg`
extension are used to demonstrate the output of the rendering engine.

**TODO:** add an explanation of how to run these integration tests
and their requirements.


# Test Dependencies
## Test Dependencies

The tests for **Units.pm** have brought in a new module dependency,
[Test2](https://metacpan.org/pod/Test2::V0) which is the state of the art in
testing Perl modules. It can compare data structures, examine warnings and
catch fatal errors thrown under expected conditions. It provides many tools
testing Perl modules. It can compare data structures, examine warnings and
catch fatal errors thrown under expected conditions. It provides many tools
for testing and randomly executes its subtests to avoid the programmer
depending on stateful data.

To make these easier to install with
[cpanm](https://metacpan.org/dist/App-cpanminus/view/bin/cpanm), there is a
[cpanfile](https://metacpan.org/dist/Module-CPANfile/view/lib/cpanfile.pod)
in the root directory. Use
in the root directory. Use

cpanm --installdeps .
cpanm --installdeps .

which will install the runtime and test dependencies.
To use the cpanfile for a minimal install skipping the test requirements,
Expand Down
58 changes: 39 additions & 19 deletions t/build_PG_envir.pl
Original file line number Diff line number Diff line change
@@ -1,43 +1,63 @@
use warnings;
#!/usr/bin/env perl

use strict;
use warnings;

package main;
die "PG_ROOT not found in environment.\n" unless $ENV{PG_ROOT};
use lib "$ENV{PG_ROOT}/lib";

$main::macros_dir = "$main::pg_dir/macros";
my $macros_dir = "$ENV{PG_ROOT}/macros";

# use WeBWorK::Localize;
use PGcore;
use Parser;

# build up enough of a PG environment to get things running

our %envir = ();
$envir{htmlDirectory} = "/opt/webwork/courses/daemon_course/html";
$envir{htmlURL} = "http://localhost/webwork2/daemon_course/html";
$envir{tempURL} = "http://localhost/webwork2/daemon_course/tmp";
$envir{pgDirectories}->{macrosPath} = ["$main::macros_dir"];
$envir{macrosPath} = ["$main::macros_dir"];
$envir{displayMode} = "HTML_MathJax";
$envir{language} = "en-us";
$envir{language_subroutine} = sub { return @_; }; # return the string passed in instead going to maketext
# Build up enough of a PG environment to get things running.
$main::envir{htmlDirectory} = '/opt/webwork/courses/daemon_course/html';
$main::envir{htmlURL} = 'http://localhost/webwork2/daemon_course/html';
$main::envir{tempURL} = 'http://localhost/webwork2/daemon_course/tmp';
$main::envir{pgDirectories}{macrosPath} = [$macros_dir];
$main::envir{macrosPath} = [$macros_dir];
$main::envir{displayMode} = 'HTML_MathJax';
$main::envir{language} = 'en';
$main::envir{language_subroutine} = sub { return $_[0]; };

$main::envir{functAbsTolDefault} = 0.001;
$main::envir{functLLimitDefault} = 0.0000001;
$main::envir{functMaxConstantOfIntegration} = 1E8;
$main::envir{functNumOfPoints} = 3;
$main::envir{functRelPercentTolDefault} = 0.1;
$main::envir{functULimitDefault} = 0.9999999;
$main::envir{functVarDefault} = 'x';
$main::envir{functZeroLevelDefault} = 1E-14;
$main::envir{functZeroLevelTolDefault} = 1E-12;
$main::envir{numAbsTolDefault} = 0.001;
$main::envir{numFormatDefault} = '';
$main::envir{numRelPercentTolDefault} = 0.1;
$main::envir{numZeroLevelDefault} = 1E-14;
$main::envir{numZeroLevelTolDefault} = 1E-12;
$main::envir{useBaseTenLog} = 0;
$main::envir{defaultDisplayMatrixStyle} = '[s]';

sub be_strict {
require 'ww_strict.pm';
require ww_strict;
strict::import();
return;
}

sub PG_restricted_eval {
WeBWorK::PG::Translator::PG_restricted_eval(@_);
my @input = @_;
return WeBWorK::PG::Translator::PG_restricted_eval(@input);
}

sub check_score {
my ($correct_answer, $ans) = @_;
return $correct_answer->cmp->evaluate($ans)->{score};
}

require "$main::macros_dir/PG.pl";
do "$macros_dir/PG.pl";

DOCUMENT();

loadMacros("PGbasicmacros.pl");
loadMacros('PGbasicmacros.pl');

1;
38 changes: 14 additions & 24 deletions t/contexts/fraction.t
Original file line number Diff line number Diff line change
@@ -1,38 +1,28 @@
use Test2::V0;
#!/usr/bin/env perl

# should I "use" Parser Value Parser::Legacy here instead?
=head1 Fraction context

use lib 't/lib';
use Test::PG;

=head2 Fraction context

To test the reduction of fractions
Test the fraction context defined in contextFraction.pl.

=cut

loadMacros("PGstandard.pl", "MathObjects.pl", "contextFraction.pl");
use Test2::V0 '!E', { E => 'EXISTS' };

# dd @INC;
die "PG_ROOT not found in environment.\n" unless $ENV{PG_ROOT};
do "$ENV{PG_ROOT}/t/build_PG_envir.pl";

for my $module (qw/Parser Value Parser::Legacy/) {
eval "package Main; require $module; import $module;";
}
use lib "$ENV{PG_ROOT}/lib";

# use Value;
# use Value::Complex;
# # use Value::Type;
# use Parser::Context::Default;
# use Parser::Legacy;
# use Parser::Context;
loadMacros('PGstandard.pl', 'MathObjects.pl', 'contextFraction.pl');

Context("Fraction");
use Value;
require Parser::Legacy;
import Parser::Legacy;

# require("Parser::Legacy::LimitedNumeric::Number");
# require("Parser::Legacy");
Context('Fraction');

ok my $a1 = Compute("1/2");
ok my $a2 = Compute("2/4");
ok my $a1 = Compute('1/2');
ok my $a2 = Compute('2/4');

is $a1->value, $a2->value, 'contextFraction: reduce fractions';

Expand Down
28 changes: 15 additions & 13 deletions t/contexts/integer.t
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
use Test2::V0;
#!/usr/bin/env perl

# should I "use" Parser Value Parser::Legacy here instead?
=head1 Integer context

use lib 't/lib';
use Test::PG;
Test contextInteger.pl methods.

=head2 Integer context
=cut

To test for greatest common denomenators and such like.
use Test2::V0 '!E', { E => 'EXISTS' };

=cut
die "PG_ROOT not found in environment.\n" unless $ENV{PG_ROOT};
do "$ENV{PG_ROOT}/t/build_PG_envir.pl";

use lib "$ENV{PG_ROOT}/lib";

loadMacros("MathObjects.pl", "contextInteger.pl");
loadMacros('MathObjects.pl', 'contextInteger.pl');

for my $module (qw/Parser Value Parser::Legacy/) {
eval "package Main; require $module; import $module;";
}
use Value;
require Parser::Legacy;
import Parser::Legacy;

Context("Integer");
Context('Integer');

my $b = Compute(gcd(5, 2));
ANS($b->cmp);

ok(1, "integer test: dummy test");
ok(1, 'integer test: dummy test');

done_testing();
56 changes: 29 additions & 27 deletions t/contexts/toltype_digits.t
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
use Test2::V0;
#!/usr/bin/env perl

use lib 't/lib';
use Test::PG;
=head1 TolType context

=head2 TolType context

To test for tolerances
Test MathObjects tolerances.

=cut

loadMacros("PGstandard.pl", "MathObjects.pl");
use Test2::V0 '!E', { E => 'EXISTS' };

die "PG_ROOT not found in environment.\n" unless $ENV{PG_ROOT};
do "$ENV{PG_ROOT}/t/build_PG_envir.pl";

loadMacros('PGstandard.pl', 'MathObjects.pl');

my $ctx = Context("Numeric");
my $pi = Real("pi");
my $ctx = Context('Numeric');
my $pi = Real('pi');

subtest 'set tolTrunction to 1' => sub {
$ctx->flags->set(tolType => 'digits', tolerance => 3, tolTruncation => 1);

is check_score($pi, Compute("3.14")), 1, "toltype digits: pi is 3.14";
is check_score($pi, Compute("3.141")), 1, "toltype digits: pi is 3.141";
is check_score($pi, Compute("3.142")), 1, "toltype digits: pi is 3.142";
is check_score($pi, Compute("3.143")), 0, "toltype digits: pi is not 3.143";
is check_score($pi, Compute("3.15")), 0, "toltype digits: pi is not 3.15";
is check_score($pi, Compute('3.14')), 1, 'toltype digits: pi is 3.14';
is check_score($pi, Compute('3.141')), 1, 'toltype digits: pi is 3.141';
is check_score($pi, Compute('3.142')), 1, 'toltype digits: pi is 3.142';
is check_score($pi, Compute('3.143')), 0, 'toltype digits: pi is not 3.143';
is check_score($pi, Compute('3.15')), 0, 'toltype digits: pi is not 3.15';
};

subtest 'set tolTrunction to 0' => sub {
$ctx->flags->set(tolType => 'digits', tolerance => 3, tolTruncation => 0);

is check_score($pi, Compute("3.14")), 1, "toltype digits: pi is 3.14";
is check_score($pi, Compute("3.141")), 0, "toltype digits: pi is not 3.141";
is check_score($pi, Compute("3.142")), 1, "toltype digits: pi is not 3.142";
is check_score($pi, Compute("3.143")), 0, "toltype digits: pi is not 3.143";
is check_score($pi, Compute("3.15")), 0, "toltype digits: pi is not 3.15";
is check_score($pi, Compute('3.14')), 1, 'toltype digits: pi is 3.14';
is check_score($pi, Compute('3.141')), 0, 'toltype digits: pi is not 3.141';
is check_score($pi, Compute('3.142')), 1, 'toltype digits: pi is not 3.142';
is check_score($pi, Compute('3.143')), 0, 'toltype digits: pi is not 3.143';
is check_score($pi, Compute('3.15')), 0, 'toltype digits: pi is not 3.15';
};

subtest 'set tolExtraDigits to 2' => sub {
Expand All @@ -42,15 +44,15 @@ subtest 'set tolExtraDigits to 2' => sub {
tolExtraDigits => 2
);

is check_score($pi, Compute("3.14")), 1, "toltype digits: pi is 3.14";
is check_score($pi, Compute("3.141")), 0, "toltype digits: pi is not 3.141";
is check_score($pi, Compute("3.142")), 1, "toltype digits: pi is not 3.142";
is check_score($pi, Compute("3.143")), 0, "toltype digits: pi is not 3.143";
is check_score($pi, Compute("3.15")), 0, "toltype digits: pi is not 3.15";
is check_score($pi, Compute('3.14')), 1, 'toltype digits: pi is 3.14';
is check_score($pi, Compute('3.141')), 0, 'toltype digits: pi is not 3.141';
is check_score($pi, Compute('3.142')), 1, 'toltype digits: pi is not 3.142';
is check_score($pi, Compute('3.143')), 0, 'toltype digits: pi is not 3.143';
is check_score($pi, Compute('3.15')), 0, 'toltype digits: pi is not 3.15';

is check_score($pi, Compute("3.1416")), 1, "toltype digits: pi is 3.1416";
is check_score($pi, Compute("3.1415888")), 1, "toltype digits: pi is 3.1415888";
is check_score($pi, Compute("3.1415")), 0, "toltype digits: pi is not 3.1415";
is check_score($pi, Compute('3.1416')), 1, 'toltype digits: pi is 3.1416';
is check_score($pi, Compute('3.1415888')), 1, 'toltype digits: pi is 3.1415888';
is check_score($pi, Compute('3.1415')), 0, 'toltype digits: pi is not 3.1415';
};

done_testing();
Loading