How can I run only a specific test in a Perl distribution? - perl

This question is related to this question I asked before. I have multiple test files (A.t, B.t, C.t etc) created to test their respective module A, B, C & so on. But when I do a make test, it runs all the tests. But, when I'm working on a specific module say B, I'd like to run unit tests for that module. After I'm done with my changes, I'll run the whole suite.
So is there any way to do like make test B, which will run only the tests using B.t? And when I say some thing like "make test all" it runs all the tests under the "t" dir? Thanks.

I just run the test that I want to run:
% make; perl -Mblib t/B.t
You can do the same thing with prove, too.
That -Mblib loads the module blib which merely adds blib/lib (and various special directories under it) to #INC for you. It comes with Perl. prove should do the same thing with the -b switch.
My command is really two parts: the make (or ./Build for Module::Build). This builds the source and moves Perl modules and other files into the "build library", or blib, as an intermediate step in the full installation. Normally make test works against the versions in blib and refreshes that for me. Since I'm testing on my own, I ensure that I refresh blib myself and include it in Perl's module search path.
Despite the fact that I know all this, you might be surprised that I often forget to do one of those steps and end up testing against the wrong version of things, whether the fully installed old version (forgot -Mblib) or the old development sources (forgot make). This leads me to debugging statements such as:
print "No really, this is the Foo version. kthnxbye\n";

Executing tests directly through perl works. The prove command was designed to simplify the process, save keystrokes, and shorten the test-debug-test cycle.
prove was designed to work on multiple tests at a time, which you can't do invoking via perl. For instance, you can do:
prove t/*.t
prove t/ # Same as t/*.t
prove t/dev/ # Run only tests in t/dev/
prove -r t/ # Runs all .t files in t/ and any directories below.
The modern prove also has many features for handling suites of tests and modifying how the TAP output from the tests is displayed.
prove --help will show you all prove's options, and prove --man will show you the manual page.

Related

Split Test::More suite into multiple files

I'm using Test::More to test my application. I have a single script, run_tests.pl, that runs all the tests. Now I want to split this into run_tests_component_A.pl and B, and run both test suites from run_tests.pl. What is the proper way of doing this, does Test::More have any helpful methods?
I'm not using any build system.
Instead of running the creating a run_tests.pl to run the test suite, the standard practice is to use prove.
Say you have
t/foo.t
t/bar.t
Then,
prove is short for prove t.
prove t runs the entire test suite (both t/foo.t and t/bar.t).
prove t/foo.t runs that specific test file.
perl t/foo.t runs that specific test file, and you get the raw output. Easier for debugging.
perl -d t/foo.t even allows you to run the test in the debugger.
Each file is a self-standing program. If you need to share code between test programs, you can create t/lib/Test/Utils.pm (or whatever) and use the following in your test files:
use FindBin qw( $RealBin );
use lib "$RealBin/lib";
use Test::Utils;
prove executes the files in alphabetical order, so it's common to name the files
00_baseline.t
01_basic_tests.t
02_more_basic_tests.t
03_advanced_tests.t
The 00 test tests if the modules can be loaded and that's it. It usually outputs the versions of loaded modules to help with dependency problems. Then you have your more basic tests. The stuff that's like "if this doesn't work, you have major problems". There's no point in testing the more complex features if the basics don't work.

How to run perl test without t/*.t structure(t/sub_folder/*.t)

I try to gather my code and manage my perl project via Makefile.PL or Build.PL, everything goes well and I got the correct test result with TAP format. But I'd like to make some sub folders under t/ folder to gather different test file, then I found that when I run make test, ./Build test or prove, they say no tests. Is there any way to resolve this?
It's up to the build module(s) to tell Test::Harness which files to run, so that's the documentation you need to look in. If you're using ExtUtils::MakeMaker, for example, you can search for RECURSIVE_TEST_FILES to find the relevant bit.

What is the proper way to test perl modules during development?

I'm working on a personal Perl module to build a basic script framework and to help me learn more about the language. I've created a new module called "AWSTools::Framework" with ExtUtils::ModuleMaker via the command line tool modulemaker. I'm trying to figure out the appropriate way to test it during development.
The directory structure that was created includes the following:
./AWSTOOLS/Framework/lib/AWSTools/Framework.pm
./AWSTOOLS/Framework/t/001_load.t
The autogenerated 001_load.t file looks like this:
# -*- perl -*-
# t/001_load.t - check module loading and create testing directory
use Test::More tests => 2;
BEGIN { use_ok( 'AWSTools::Framework' ); }
my $object = AWSTools::Framework->new ();
isa_ok ($object, 'AWSTools::Framework');
If I try to run the script directly (either from the command line or inside my TextMate editor), it fails with:
Can't locate AWSTools/Framework.pm in #INC....
If I try to run prove in the ./AWSTOOLS/Framework directory, it fails as well.
The question is: What is the proper way to run the tests on Perl modules while developing them?
If you want to run a single test file, you need to tell perl where to find your modules just like you would for any other program. I use the blib to automatically add the right paths:
$ perl Makefile.PL; make; perl -Mblib t/some_test.t
You can also use prove to do the same thing. I don't use prove, but you can read its documentation to figure it out. The -b switch should do that, but I've had problems with it not doing the right thing (could just be my own idiocy).
If you're using the typical toolchain (ExtUtils::MakeMaker) it will be perl Makefile.PL to generate a makefile, then make test every time afterward. Those commands should be run from the root directory of the module. See http://search.cpan.org/perldoc?ExtUtils::MakeMaker#make_test
Edit: and don't do it all manually, or you will come to hate testing. (Well, more than usual.) You will also want to look at least briefly at Test::Tutorial and https://www.socialtext.net/perl5/testing
You may also want to ask the friendly* people in #perl or related channels on your preferred IRC networks.
*Not actually friendly
I actually think that Dist::Zilla is sufficiently flexible enough to allow you to use it for all development. If you aren't uploading to CPAN, just make sure you don't have [UploadToCPAN] in your dist.ini. Also make sure to [#Filter] it out of any plugin bundles which provide it.
Dist::Zilla may be too much to install for only one quick module that you aren't going to touch very often. If you have more than one dist in development then it is definitely worth a look.
You can easily interface it with your VCS using plugins. (Including Git)
You can create a plugin to deploy onto your server. Which would allow you to make sure that all your test files pass before allowing you to deploy ([TestRelease]).
If you don't like tabs in your source files, you can test for that without writing the test yourself ([NoTabsTests]).
Minimal dist.ini for non-CPAN dist
name = Your-Library
author = E. Xavier Ample <example#example.org>
license = Perl_5
copyright_holder = E. Xavier Ample <example#example.org>
copyright_year = 2012
version = 0.001
[GatherDir]
[PruneCruft]
[PruneFiles]
filename = dist.ini
filename = TODO.txt
match = ^.*[.]te?mp$
[NoTabsTests]
[TestRelease]
[CheckExtraTests]
[ModuleBuild]
[FakeRelease]
Test the dist:
dzil test
dzil xtest
If at a later date, you decide to upload it to CPAN:
Replace [FakeRelease] with [UploadToCPAN].
Get a PAUSE id, and set ~/.pause.
user YOUR-PAUSE-ID
password YOUR-PAUSE-PASSWORD
Run dzil release
DONE
In a quick attempt to help you, I would recommend looking at Testing Files and Test Modules.
Continuing to dig around and experiment, I've found the following two things which work for me:
Use prove -l in the './AWSTOOLS/Framework' directory. According to the prove perldoc page, it adds the "lib" directory to the path when Perl runs all the tests in the "t" directory.
To run the script individually/directly, I'm adding the following to the start of the script above the use Test::More line:
use FindBin qw($Bin);
use lib "$Bin/../lib";
This let's me run the script directly via the commad line and in my editor (TextMate). This is based off this page from the Programming Perl book.
Using the -l flag for prove seems very much like the correct thing to do.
As for the "use lib" solution, I doubt that's actually a best practice. If it was, I would expect that modulemaker would have created the 001_load.t test file with that to begin with.

Do I have to run make/make install to test each change to a Perl distribution file?

Do I have to run make and make install each time I change a .pm file for Perl? I'm doing a ton of testing and this is becoming cumbersome.
You don't have to install the module to test it.
If I'm testing inside my distribution directory, I just use the test target:
% make test
Or, if I'm using Module::Build:
% ./Build test
Since make is a dependency management tool, it also takes care of any other steps it needs to perform so it can run the test target. You don't need to run each target separately. Module::Build does the same thing.
If I want to test a single file, I combine the make command with a call to perl that also uses the blib module to set the right #INC:
% make; perl -Mblib t/single_test.t
Some people like using prove for the same thing. No matter which method I use, I'm probably using the arrow keys to move back to a previous command line to re-run it. I do very little typing in any of this.
It depends on module setup, but under the standard MakeMaker I use, "make test" runs a "make" if any files have been modified, so when doing intra-module development "make test" is the only command you need until you've finished.
Evan Carroll got it basically right. To expand on his answer: use the testing tools that come with Perl to tighten the workflow.
Let's say you are in your project directory and you hack on the files in its lib/ subdirectory. Execute prove -l to run all tests. That's easier than messing with absolute paths in the PERL5LIB environment variable.
Presumably you're editing a lib module in a non-lib location, rather than clobbering a global library for each modification - do the sensible thing and change the library path perl uses with PERL5LIB, which will append internally to #INC (the use search path):
PERL5LIB=/home/user/code/perl/project/lib perl myapp.pl
If your program isn't pure-perl and requires a make system, there is no way to do this short of rebuilding, but pure-perl (PP) doesn't really require make under normal circumstances. If you do it this way, running perl under a normal environment will yield the predictable and tested results, running it with your PERL5LIB will allow you to test the program.

How do I find the module dependencies of my Perl script?

I want another developer to run a Perl script I have written. The script uses many CPAN modules that have to be installed before the script can be run. Is it possible to make the script (or the perl binary) to dump a list of all the missing modules? Perl prints out the missing modules’ names when I attempt to run the script, but this is verbose and does not list all the missing modules at once. I’d like to do something like:
$ cpan -i `said-script --list-deps`
Or even:
$ list-deps said-script > required-modules # on my machine
$ cpan -i `cat required-modules` # on his machine
Is there a simple way to do it? This is not a show stopper, but I would like to make the other developer’s life easier. (The required modules are sprinkled across several files, so that it’s not easy for me to make the list by hand without missing anything. I know about PAR, but it seems a bit too complicated for what I want.)
Update: Thanks, Manni, that will do. I did not know about %INC, I only knew about #INC. I settled with something like this:
print join("\n", map { s|/|::|g; s|\.pm$||; $_ } keys %INC);
Which prints out:
Moose::Meta::TypeConstraint::Registry
Moose::Meta::Role::Application::ToClass
Class::C3
List::Util
Imager::Color
…
Looks like this will work.
Check out Module::ScanDeps and the "scandeps.pl" utility that comes with it. It can do a static (and recursive) analysis of your code for dependencies as well as the %INC dump either after compiling or running the program.
Please note that the static source scanning always errs on the side of including too many dependencies. (It is the dependency scanner used by PAR and aims at being easiest on the end-user.)
Finally, you could choose to distribute your script as a CPAN distribution. That sounds much more complicated than it really is. You can use something like Module::Starter to set up a basic skeleton of a tentative App::YourScript distribution. Put your script in the bin/ subdirectory and edit the Makefile.PL to reference all of your direct dependencies. Then, for distribution you do:
perl Makefile.PL
make
make dist
The last step generates a nice App-YourScript-VERSION.tar.gz
Now, when the client wants to install all dependencies, he does the following:
Set up the CPAN client correctly. Simply run it and answer the questions. But you're requiring that already anyway.
"tar -xz App-YourScript-VERSION.tar.gz && cd App-YourScript-VERSION"
Run "cpan ."
The CPAN client will now install all direct dependencies and the dependencies of those distributions automatically. Depending on how you set it up, it will either follow the prerequisites recursively automatically or prompt with a y/n each time.
As an example of this, you might check out a few of the App::* distributions on CPAN. I would think App::Ack is a good example. Maybe one of the App::* distributions from my CPAN directory (SMUELLER).
You could dump %INC at the end of your script. It will contain all used and required modules. But of course, this will only be helpful if you don't require modules conditionally (require Foo if $bar).
For quick-and-dirty, infrequent use, the %INC is the best way to go. If you have to do this with continuous integration testing or something more robust, there are some other tools to help.
Steffen already mentioned the Module::ScanDeps.
The code in Test::Prereq does this, but it has an additional layer that ensures that your Makefile.PL or Build.PL lists them as a dependency. If you make your scripts look like a normal Perl distribution, that makes it fairly easy to check for new dependencies; just run the test suite again.
Aside from that, you might use a tool such as Module::Extract::Use, which parses the static code looking for use and require statements (although it won't find them in string evals). That gets you just the modules you told your script to load.
Also, once you know which modules you loaded, you can combine that with David Cantrell's CPANdeps tool that has already created the dependency tree for most CPAN modules.
Note that you also have to think about optional features too. Your code in this case my not have them, but sometimes you don't load a module until you need it:
sub foo
{
require Bar; # don't load until we need to use it
....
}
If you don't exercise that feature in your trial run or test, you won't see that you need Bar for that feature. A similar problem comes up when a module loads a different set of dependency modules in a different environment (say, mod_perl or Windows, and so on).
There's not a good, automated way of testing optional features like that so you can get their dependencies. However, I think that should be on my To Do list since it sounds like an interesting problem.
Another tool in this area, which is used by Dist::Zilla and its AutoPrereqs plugin, is Perl::PrereqScanner. It installs a scan-perl-prereqs program that will use PPI and a few plugins to search for most kinds of prereq declaration, using the minimum versions you define. In general, I suggest this over scanning %INC, which can bring in bogus requirements and ignores versions.
Today I develop my Perl apps as CPAN-like distributions using Dist::Zilla that can take care of the dependencies through the AutoPrereq plugin. Another interesting piece of code in this area is carton.