Re: prove can't find my module, even though its directory is in $INC[0]
by choroba (Cardinal) on Dec 14, 2025 at 23:30 UTC
|
It seems your test uses require with a string value, e.g.
require 'MAS::Global';
# or
my $class = 'MAS::Global';
require $class;
That's not how require works. In fact, the documentation of the command tells you exactly that:
If EXPR is a bareword, "require" assumes a .pm extension and
replaces "::" with "/" in the filename for you, to make it easy
to load standard modules. This form of loading of modules does
not risk altering your namespace.
In other words, if you try this: require Foo::Bar; # a splendid bareword
The require function will actually look for the Foo/Bar.pm file
in the directories specified in the @INC array.
But if you try this:
my $class = 'Foo::Bar';
require $class; # $class is not a bareword
#or
require "Foo::Bar"; # not a bareword because of
+the ""
The require function will look for the Foo::Bar file in the @INC
array and will complain about not finding Foo::Bar there. In
this case you can do:
eval "require $class";
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
| [reply] [d/l] [select] |
|
|
I will add that if they are doing that, it seems like they are trying to explicitly test that the module loads ok, but in a non-standard way.
The old Test::More framework has a use_ok function, but it is a good idea to only use it in a test file that just does that one test, since other tests may be impacted negatively by not having the module loaded at compile time.
The new Test2 removes use_ok and just recommends a regular use of the module in your test files.
| [reply] |
|
|
No, the test file t/8bit.t uses a simple use MAS::Global;. I just checked.
| [reply] [d/l] |
|
|
Can't locate MAS::Global in @INC [...]
The error message indicates that Perl is looking for a file named MAS::Global when you want it to look for a file named MAS/Global.pm.
This happens, like choroba said, when require "MAS::Global"; is used instead of require MAS::Global; or require "MAS/Global.pm";.
$ perl -e'require "MAS::Global";' # Bad
Can't locate MAS::Global in @INC [...] at -e line 1.
$ perl -e'require MAS::Global;' # Ok
Can't locate MAS/Global.pm in @INC [...] at -e line 1.
$ perl -e'require "MAS/Global.pm";' # Ok
Can't locate MAS/Global.pm in @INC [...] at -e line 1.
So check again, because require "MAS::Global"; or equivalent is definitely used somewhere in your code. The full error message will even say in what file and on what line. Add use Carp::Always; if you need a stack trace.
If you're still unable to find the problem, start by providing the full (unedited) error message.
In case you need it, the following is a portable method of converting a package name to a path for require:
# Equivalent to what `if.pm` uses.
my $require_path = $pkg_name =~ s{::}{/}gr . ".pm";
| [reply] [d/l] [select] |
|
|
That's weird, because using a bareword replaces the :: with a slash, so the error should be
Can't locate MAS/Global.pm in @INC (you may need to install the MAS::G
+lobal module) (@INC contains: ...
# ^
# |
# slash
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
| [reply] [d/l] [select] |
Re: prove can't find my module, even though its directory is in $INC[0]
by atcroft (Abbot) on Dec 15, 2025 at 08:22 UTC
|
There are two things I might suggest:
- perl -c ./t/8bit.t
- prove -I/home/henry/gitr/MAS/lib ./t/8bit.t
In the output you provided you gave perl -c /home/henry/gitr/MAS/lib/MAS/Global.pl as an example to show that perl could find it; however, that command would only check the syntax of the file name you provided (the full path to the module). By running perl -c ./t/8bit.t you have perl check the syntax of the test file (it's perl code too, after all), and if it can see the module it should pass.
prove's -I option adds a library path for prove to include when running. prove's man page includes this comment about @INC:
@INC
prove introduces a separation between "options passed to the perl which runs
prove" and "options passed to the perl which runs tests"; this distinction
is by design. Thus the perl which is running a test starts with the default
@INC. Additional library directories can be added via the "PERL5LIB"
environment variable, via -Ifoo in "PERL5OPT" or via the "-Ilib" option to
prove.
It looks as if using the -I option might add the given path you need to have the test complete successfully.
Hope that helps.
| [reply] [d/l] [select] |
|
|
My example showing how Perl could find the module was actually perldoc -l which correctly identified the source as /home/henry/gitr/MAS/lib. So Perl's own module-search routines are working OK.
I tried the -I option, with the same baffling result:
/usr/bin/prove -I/home/henry/gitr/MAS/lib ./t/8bit.t
./t/8bit.t .. Can't locate MAS::Global in @INC (@INC entries checked:
+/home/henry/gitr/MAS/lib ... etc
The section in the docs that you point out, that there's a separate set of options passed to "options passed to the perl which runs tests" is interesting; but use of the -I option, as it recommends, shows that that's not the problem either.
I remain baffled, and stymied ... | [reply] [d/l] |
|
|
Out of curiosity, what does your 'package' statement in the module look like? Is it something like package MAS::Global; , or package Global;?
I ask because I did a quick test of some code I was working on recently. My code was under ./lib/My/Particle/Moveable.pm, and my test ran correctly if I used package My::Particle::Moveable; but not if I did package Moveable;. (I remember there was some reason for doing it one way and not the other, but I can't remember it at the moment.)
Hope that helps.
| [reply] [d/l] [select] |
|
|
|
|
| [reply] |
|
|
Re: prove can't find my module, even though its directory is in $INC[0]
by pfaut (Priest) on Dec 14, 2025 at 23:11 UTC
|
Are you sure PERL5LIB is exported? Try 'env | grep PERL5LIB'. If it doesn't appear then you need to 'export PERL5LIB'.
| 90% of every Perl application is already written. ⇒ | | dragonchild |
| [reply] |
Re: prove can't find my module, even though its directory is in $INC[0]
by HenryLaw (Acolyte) on Dec 15, 2025 at 10:03 UTC
|
Curiouser and curiouser. I cloned the project onto a different (virtual) machine, also running Mint 22.2 and prove for that test file works fine. So it's definitely something I have done, but I'm no closer to finding what. | [reply] |
Re: prove can't find my module, even though its directory is in $INC[0]
by ysth (Canon) on Dec 15, 2025 at 15:36 UTC
|
Does prove --lib ... work? | [reply] [d/l] |
|
|
No; prove -l gives the same result (in fact that's what I usually enter, by force of habit).
prove -l ./t/8bit.t reports that /home/henry/gitr/MAS/lib is in the path and then fails to find Global.pm, even though /home/henry/gitr/MAS/lib/MAS/Global.pm exists, and contains contains the line package MAS::Global;
| [reply] |
|
|
contains contains the line package MAS::Global;
The package directive is irrelevant. That's not used to load a module. (It can be relevant to the later step of importing symbols when using use, but the error happens before that.)
and then fails to find Global.pm
Not quite. The issue isn't that perl can't find Global.pm (or rather, MAS/Global.pm); it's that it's not even looking for it. As previously explained, the message indicates it's looking for a file named MAS::Global (i.e. /home/henry/gitr/MAS/lib/MAS::Global). No such file exists, thus the failure.
In the earlier post where I explained this, I requested that you start by providing the complete (unedited) error message (referring the output from prove ./t/8bit.t) if you were still having issues.
| [reply] [d/l] [select] |
|
|
Can you show 8bit.t? You said this doesn't happen in a different environment, are the repo files all the same when it doesn't happen?
| [reply] |
Re: prove can't find my module, even though its directory is in $INC[0]
by HenryLaw (Acolyte) on Dec 15, 2025 at 19:09 UTC
|
More curiosity: this problem seems to be confined to this particular project (in the git sense). If I switch to another project prove -l works as expected.
I'll clone the project afresh from my git server and see if that makes any difference
| [reply] |
Re: prove can't find my module, even though its directory is in $INC[0]
by HenryLaw (Acolyte) on Dec 17, 2025 at 10:51 UTC
|
I've found the problem. Thank you to all commenters: what you said helped me to home in on it.
For those who may have a similar problem, it was the result of using "require" to load the MAS::Global module after it had already been loaded with "use". No, don't ask me why I coded it that way: it's probably because this is code re-used from another project. More specifically I had this (in summary):
use MAS::Global;
...
if ( $something_irrelevant ){
require 'MAS::Global';
}
I'll mark this "solved" if I can find out how to do it. | [reply] [d/l] |
|
|
require 'MAS::Global';
Just to hammer the point home, it is the format of this line which is the problem, not the line itself. By enclosing the module name in quotes it is no longer a bareword and therefore perl looks for a file with that exact name which of course it does not find because it does not exist. If you had omitted the quotes (as you did in the use statement) it would all have been fine. Here's a trivial illustration using a core module as an example:
$ perl -e 'use Fcntl; require "Fcntl";'
Can't locate Fcntl in @INC (@INC contains: /usr/local/lib64/perl5 /usr
+/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vend
+or_perl /usr/lib64/perl5 /usr/share/perl5) at -e line 1.
$ perl -e 'use Fcntl; require Fcntl;'
$
See how (and why) the first one with the quotes fails but the second one without the quotes succeeds? It's the same even without the use statement but I have left it in there to mirror your use case.
| [reply] [d/l] [select] |
|
|
Just edit the title of the original post, append (Solved) to it.
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
| [reply] [d/l] |
|
|
Your analysis is incorrect. It has nothing to do with the module having already been loaded.
That tries to load a file named MAS::Global (not MAS/Global.pm), and no such file has been loaded. Furthermore, it wouldn't be an error if it had been.
The error is because you used require 'MAS::Global'; instead of require MAS::Global;, just like we said. (require 'MAS/Global.pm'; would also work.)
| [reply] [d/l] [select] |