Error while running test file(.t file) in perl - perl

I am trying to write my first test case in perl with the help of Test::Simple module.
I have saved the file with .t extension now when i am trying to run this file on windows system then it says windows can not open this file.
I had googled about this and what i found is for running this file you should make a new directory with name /t and keep this file to there.
http://perlmeme.org/tutorials/writing_test_harness.html
I have tried this also but still it is not working.
Can any body gives me some tips.
following is my Test cases :
#!/usr/bin/perl -w
use Test::Simple tests => 2;
ok( 1 + 1 == 2 );
ok( 2 + 2 == 5 );

A .t file in Perl is just a Perl script. The .t is just there to let you know that it's a test script instead of something else. The file extension and directory structure really doesn't matter, it's there just to help you can keep your environment clean.
To run a Perl script on Windows, from a command line, simply type perl <script name>. Make sure that you have a Perl executable installed on your system as Windows does not come with one by default, and make sure it is in your path. If the script you want to run is not in your current directory, make sure to specify the path to the script.

In the URL you gave it says:
Now because 'dot-T' files are just normal Perl scripts, you can run them as such -
perl t/Monger.t
Is it a typo in your post, you wrote /t as a directory to keep your test files in - it should be t/, so just a directory relative to where you are. (That's "just" a convention.)

Related

Unable to execute Perl script unless Perl is inserted before script name

Running Lubuntu -
Beginner Perl programmer
Script is XXX.pl located at ~/projects/XXX/XXX.pl
First line is the shebang
#!/usr/bin/perl
Permission to run is set to Anyone.
In directory ~/projects/XXX, the command
~/projects/XXX$ perl XXX.pl
works as desired, but the command
~/projects/XXX$ XXX.pl
Fails with XXX.pl: command not found
What am I missing ?
The two usual options to execute your Perl script are:
perl XXX.pl
or
./XXX.pl
Both ways assume that your current working directory contains the script XXX.pl, otherwise it won't work.
As already pointed out by jm666 in the comments, you can usually not execute a program or script from your current working directory without prepending ./, primarily because of security reasons. Now, you may wonder why it's necessary.
Explanation:
Your shell uses the contents of an environment variable called $PATH to find out about where external commands (non-builtin programs) are located in your filesystem. If you want to see what's in $PATH, just type the following in your shell:
echo $PATH
Now you can see that the $PATH variable does NOT contain your current working directory. The consequence is that your shell is not able to find the program XXX.pl. By prepending ./ you instruct the shell to execute the program which comes after.
But there are two requirements if you want to execute your Perl script with ./script.pl:
The script has to be executable (check with ls -l)
The first line (shebang line) has to be #!/path/to/your/perl because your shell needs that information to find the perl interpreter in order to run your script
However, #1 and #2 are NOT required when you execute your script with
perl XXX.pl
because it invokes the perl interpreter directly with your script.
See how to make Perl scripts executable on Linux and make the script itself directly executable with chmod for some more details.
Can the script be found?
Is . in your path? If it's not, add it to your path, or use ./XXX.pl instead of XXX.pl.
Can the script be executed?
Do you have execute permission to the file? Fix using chmod u+x XXX.pl.
Is the interpreter correct?
which perl will tell you which interpreter is used when you use perl XXX.pl. That's the path that should be on your shebang (#!) line.

Trouble Running Perl Script from within Shell Script

I am trying to run a perl script from within a *.csh script, but I get the following error:
Can't open perl script "checkLength.perl": No such file or directory
I think it has something to do with the path of the perl script. I can run a perl script fine when it's not being called within the shell script, but a perl script won't run when I have it being called in the cshell script.
The shebang I use for the perl script is : #!/usr/bin/perl. I checked, and perl is located there (not in /usr/bin/env perl). I made sure it's executable.
Do I need to edit the $PATH to get this to work? I'm confused because if I run a perl script without calling it within another csh script, it runs just fine.
Of course one obvious solution to your problem would be to simply use the full path to the script. But this is often not preferable, as the script would brake on installations that do not mirror exactly the original structure.
So there are two possibilities:
Either you put your perl script into a well defined location that is contained in your PATH variable so any program that runs under the respective users environment finds it.
Or you have some well defined location relative to the location of your calling script. Say your bash script is located in somedir and you perl script is in somedir/subdir, then your call would be subdir/perlscript.pl. Then, to become independent of possible changes in the working directory of the caller, you could determine the current full path of the perl script to be called on start of the bash script.
A template for this would be:
#!/bin/bash
FULLPATH=$(pwd)/subdir/somescript.pl
# do something else, cd ...
$FULLPATH
I am assuming your Perl script is kept in a fixed path relative to your bash script. Assuming your directory structure to be like so:
(BASEDIR)/bin/example.sh
(BASEDIR)/perl/example.pl
To allow you to run your bash script from anywhere in your system you must specify the relative path to your Perl script by getting the BASEDIR.
#!/bin/bash
BASEDIR=$(dirname $0)
perl $BASEDIR/../perl/example.pl
What we are doing above is finding the location of your bash script(BASEDIR/bin) that you call and then finding the relative location of the Perl script using the location of the bash script as reference. Now you will be able to call the bash script from anywhere and run your Perl script normally.

How can I run a test perl script designed for prove form inside TextMate?

I'm using TextMate 1.5.10 (Mac OSX 10.7.2) to write a perl modulino application. To verify the functionality, I'm using test scripts designed to be run with the prove command line tool.
An example of the directory structure I'm using looks like this:
text_mate_test/MyModule.pm
text_mate_test/t/001_load_test.t
The 001_load_test.t file looks like this:
#!/usr/bin/perl
use Modern::Perl;
use Test::More;
use MyModule;
my $testObj = new_ok("MyModule", undef, "Initial load test.");
done_testing();
When I run prove or prove -v in the "text_mate_test" directory, everything passes as expected.
I'd like to be able to setup a hotkey in TextMate that allows me to run the test file without having to jump over to the terminal. Currently, if I run "001_load_test.t" directly from inside TextMate with Cmd+R, it chokes saying "Can't locate MyModule.pm in #INC". That's expected since the test script isn't designed to run directly. (I'm still pretty new to writing test files, but I believe that's the proper way to set them up.)
Running off the assumption that I don't want to change the test file itself, is there a way to setup a hotkey so I can run the file accurately from inside TextMate?
I've figured out an even better way to do this.
In the TextMate Bundle Editor (Menubar -> Bundles -> Bundle Editor -> Show Bundle Editor), I've updated the default "Perl -> Run Script" bundle to this:
#!/usr/bin/env ruby
require "#{ENV["TM_SUPPORT_PATH"]}/lib/tm/executor"
require "#{ENV["TM_SUPPORT_PATH"]}/lib/tm/save_current_document"
TextMate.save_current_document
TextMate::Executor.make_project_master_current_document
### If it's a ".t" test script in a "t" directory, run prove
if ( ENV["TM_FILEPATH"] =~ /^.*\/(t\/[^\/]+)$/ )
### Grab the relative file path for more legible output
relative_file_path = $1
### Jump up one directory so prove will work
Dir.chdir("../");
### Call prove with args to run only the file you are working on.
TextMate::Executor.run("prove", :script_args => ["-v", relative_file_path]);
### Otherwise, run with perl
else
TextMate::Executor.run(ENV["TM_PERL"] || "perl", "-I#{ENV["TM_BUNDLE_SUPPORT"]}",
"-Mexception_handler", ENV["TM_FILEPATH"],
:version_args => ["-e", 'printf "Perl v%vd", $^V;'])
end
Here's a screenshot of how it looks in the Bundle Editor.
The benefit of this is that you can use the same hot key (Cmd+r by default) to run your normal scripts with perl and your test scripts with prove.
This is what I was looking for.
UPDATED: When I first developed this, I only had one test script in the "t" directory. I didn't notice until I added other test scripts that the code in the original version of this answer would run prove across all the scripts. Not just the one being worked on. To get back to the expected behavior, I've update the bundle code so that prove will only run on the active script.
I've come up with a solution. Create a new Perl bundle called "Run Script with prove" and associate it with Shift-Cmd-R. The code for the bundle is:
#!/usr/bin/env ruby
require "#{ENV["TM_SUPPORT_PATH"]}/lib/tm/executor"
require "#{ENV["TM_SUPPORT_PATH"]}/lib/tm/save_current_document"
TextMate.save_current_document
TextMate::Executor.make_project_master_current_document
### If it's a ".t" test script in a "t" directory, run prove
if ( ENV["TM_FILEPATH"] =~ /^.*\/(t\/[^\/]+)$/ )
### Use the relative file path for more legible output
relative_file_path = $1
### Jump up one directory so prove will work
Dir.chdir("../");
### Call prove with args to run only the file you are working on.
TextMate::Executor.run("prove", :script_args => ["-v", relative_file_path]);
else
error_string = "This script's filepath doesn't end with /t/.*\.t\n"
error_string += "That is required for the 'Perl -> Run Script with prove' bundle to work.\n"
TextMate::Executor.run("echo", :script_args => [error_string]);
end
Note: This is the results of a bunch of trial and error hacking. I don't know if it's the "right" to do it, but this works for me. Everything but the last two lines is a copy from the original "Run Script" bundle that comes with TextMate. Based on that, it seems like this should be pretty safe.
UPDATE: When I first built this I only had one test file in the "t" directory. When I added more, I discovered that the original version of the bundle was running all the test files. This code represents an update to the expected behavior of only running the test script you working on. Because of the way I ended up doing that, it also became necessary to add in a fallback. If you try to run a script that doesn't match the standard test file path format, it gives an error message.
It will enable the program to find your module if you add
use lib '..';
to the top of your code (before the use MyModule). This will add the text_mate_test directory to #INC and enable Perl to find the module, though you may come across other problems with running the program directly.

How can i run perl script from anywhere in unix environment?

I have this perl script that I need to distribute to my coworkers who want to run the script from anywhere in the unix environment. What can I do on my part to make running this PERL script easy for them? For example, they can just have the PERL script somewhere in their directory and run just typing
./xyz.pl ttt.conf
with no path declared (like /home/abc/bin/ddd/xyz.pl ttt.conf).
The way I used to do it is add a "bin" directory in your home directory, and add it to the $PATH variable.. then you can add any script you want to use to that directory.
I am no longer familiar with the exact syntax, but something like:
in .bashrc:
$PATH = ( $PATH , $HOME/bin )
Then place the script in /home/user/bin (assuming $HOME == /home/user). When you reload the shell, it will be usable like any normal command/program.
ETA: See robert's comment below on syntax. Also, to allow your co-workers to use a script of yours, you can simply use a hard-coded path, such as /home/patrick/bin.
Put the script in /usr/local/bin (or anywhere else in $PATH). Your sysadmin may have to help you.
The technique I use is:
#!/usr/bin/env perl
This is a common way of getting the command interpreter to find Perl without either (a) moving the file, or (b) declaring the explicit path for Perl in the shebang.
It's mentioned under portability at: http://en.wikipedia.org/wiki/Shebang_(Unix)
You all are kind of right... but that perl script can sit in your path till the cows come home... and it ain't gonna run... until you set the executable bit....
:bin localadmin$ ./perlextip
-bash: ./perlextip: Permission denied
:bin localadmin$ chmod +x perlextip
:bin localadmin$ ./perlextip
Exit 0! Yeehaw.
Also, it should be noted that it need not be IN your path.... You can just call it by the full path, preceeded with a period and a slash, to execute it..
:/ localadmin$ ./ServiceData/UNIX/bin/extip
Exit 0! Yeehaw.
You can also create an alias for such a command in your ~/.bash_profile, or the such, which will let you make a system-wide shortcut of sorts, and you can even throw in a sudo, or the like, if you were so inclined... Then just call that "extip" by name anywhere, you'll be prompted for a password and, all will be well in the world.
alias extip='sudo ./ServiceData/UNIX/bin/extip'

How can I install CPAN modules locally without root access (DynaLoader.pm line 229 error)?

Doesn't work with other modules, but to give an example. I installed Text::CSV_XS with a CPAN setting:
'makepl_arg' => q[PREFIX=~/lib],
When I try running a test.pl script:
$ perl test.pl
#!/usr/bin/perl
use lib "/homes/foobar/lib/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi";
use Text::CSV_XS;
print "test";
I get
Can't load '/homes/foobar/lib/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/auto/Text/CSV_XS/CSV_XS.so' for module Text::CSV_XS: /homes/foobar/lib/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/auto/Text/CSV_XS/CSV_XS.so: cannot open shared object file: No such file or directory at /www/common/perl/lib/5.8.2/i686-linux/DynaLoader.pm line 229.
at test.pl line 6
Compilation failed in require at test.pl line 6.
BEGIN failed--compilation aborted at test.pl line 6.
I traced the error back to DynaLoader.pm it happens at this line:
# Many dynamic extension loading problems will appear to come from
# this section of code: XYZ failed at line 123 of DynaLoader.pm.
# Often these errors are actually occurring in the initialisation
# C code of the extension XS file. Perl reports the error as being
# in this perl code simply because this was the last perl code
# it executed.
my $libref = dl_load_file($file, $module->dl_load_flags) or
croak("Can't load '$file' for module $module: ".dl_error());
CSV_XS.so exists in the above directory
When you installed the module, did you watch the output? Where did it say it installed the module? Look in lib. Do you see the next directory you expect?
Look in ~/lib to see where eveything ended up to verify that you have the right directory name in your use lib statement:
% find ~/lib -name CSV_XS.so
Once you see where it is installed, use that directory name in your use lib (or PERL5LIB or whatever).
I expect you have a lib/lib in there somehow. The PREFIX is just the, well, prefix, and the installer appends other directory portions to that base path. That includes lib, man, bin, etc.
Personally I would suggest to use local::lib. :)
Try this instead:
'makepl_arg' => q[PREFIX=~/]
PREFIX sets the base for all the directories you will be installing into (bin, lib, and so forth.)
You may also be running into shell expansion problems with your '~'. You can try to expand it yourself:
'makepl_arg' => q[PREFIX=/home/users/foobar]
It would also be helpful if you included the commands you used to get the error you are asking about.
It looks from the error message ("at /www/common ...") that your script is a CGI or mod_perl script. The web server is probably not running as the user 'foo', under whose home directory you've installed the module - that could result in the web server being unable to read that directory.
It may also be running in a "chroot jail", which would mean that the directory in which you've installed the module may not be visible to the script.
In other words, just because you can see the module, does not mean that the web server, and therefore your script, can do so. You should check the relevant file permissions, and if the server is chrooted, whether your module directory is mounted within the virtual file system.
Does the file in question (CSV_XS.so) exist?
Does it exist at the listed location?
If you do:
set |grep PERL
What is the output?
Have you successfully installed other local perl modules?
I strongly suggest installing your own perl in your own home directory, if you have space. Then you can keep everything under your control and keep your own module set, as well as escaping if the admins are keeping you on an older version of perl. (Not to mention preserving yourself if they upgrade some day and leave out all the modules you are relying on.)