Test2+Test-Simple released!

This morning I uploaded Test2/Test-Simple combined into the Test-Simple distribution. You can find this distribution HERE for download. This is the result of 2 years of development on the testing infrastructure. See THIS document for important information about upgrading.

Because this is such an important module, and this release is such a big change, I have also prepared extra tarballs for Test2 and Test-Simple th…

Test2/Test::Builder stable delayed to May 10th

Last Friday Test-Simple 1.302014_009 was released. That plan was to bump that distributions version number and release it as stable this Friday May 6'th.

Since that release a number of minor bugs have been fixed. Most of these are typo fixes and documentation changes. There were also some mistakes in our x-breaks meta-data that needed to be corrected. Finally there was one bug fixed that was not as minor, a 64-byte shared memory leak when using threads.

I have decided that these fixes, in particular the last one, are important enough to put out a new dev release, and bump out …

Test2/Test::Builder Update from the QAH

Yesterday was the first day of the QA Hackathon in Rugby, UK. The first item on the agenda was a discussion about Test2 going stable. This blog post will cover the important points of that discussion.

For the impatient, here is a summary:

  • Test2 is going to be part of the Test-Simple dist. It will not be a standalone dist.
  • The next stable Test-Simple release will include Test2 and a Test::Builder that runs on Test2.
  • The release date for the next stable Test-Simple, which includes Test2, will be no sooner than Friday May 6'th, which is o…

Last call for review of Test-Builder using Test2 (Formerly Test-Stream).

On October 29th, 2015, I released Test-Stream as stable. I did this because I felt it was ready, and because I was no longer receiving any feedback from perl-qa asking me to change things. Since that release, the feedback picked up substantially. It seems that declaring something done is the best way to find out ways in which it is not actually done.

Here are the big things people wanted:

  • Split the dist into multiple dists, making the internals and tools separate.
  • Abandon the loader system (use Test::Stream -/:/etc)
  • Loosen the tight coupling of Test::Steam to TAP
  • Make context() less magic (don’t use INTERNALS::SvREFCNT)
  • Use less import() magic
  • Better namespace structuring
  • Changes to how SKIP and TODO are implemented

We decided that the best way forward was to forget about compatibility with Test-Stream, which is still new enough that it is not seeing much use, and make a new name with everyone’s changes. That’s Test2.

After the split there are 3 distributions:

Test2::Suite and Test2::Workflow are optional systems. I think you’ll find them very useful, but they’re not the key deliverable. That’s Test2, which is meant to replace Test::Builder’s guts. Test::Builder will be a backward compatibility layer on top of Test2.

As of the latest releases of Test2 and Test2-Suite I am considering the work done to my specifications and intentions. Now is the time to review these and make commentary. Once this goes stable it will become much harder, if not impossible, to make sweeping changes. If there is anything in these distributions (Test2 in particular) that makes you uncomfortable, you need to speak now. I am not yet ready to say Test2-Workflow is complete.

The work to make Test::Builder use Test2 under the hood is also complete.

On CPAN: https://metacpan.org/pod/release/EXODIST/Test-Simple-1.302013_011/lib/Test/Builder.pm

On Github: https://github.com/Test-More/test-more/tree/Test2/master

Blead Patch Ticket: https://rt.perl.org/Public/Bug/Display.html?id=127000#txn-1385453

This work has been through several verification procedures:

  • CPAN Smoking by Andreas König
  • My own testing against CPAN distributions
  • Blead patches I have written (though to date nobody has merged it in)
  • A comparison of verbose testing output on blead with and without my patch https://github.com/exodist/bleadstreamdiff

Note: The preferred form of feedback is tickets on the relevant github projects.

The problem with Exporters (Meet Importer)

The problem with Exporters

With Exporter, and most exporter tools we have failed to separate concerns. Exporting fundamentally involves 2 parties: exporter and importer. Historically however we have only ever concerned ourselves with the exporter. The "standard" way of dealing with this in perl has been to have a module that provides exports use it's import() method to inject symbols into the importer's namespace.

What if we did this with other similar concepts? What if instead of:

use base 'foo';

we had:

package My::Base;

# Gives us an import() method that sets @{caller::ISA} = __PACKAGE__
use base;


package My::Subclass;
use Base::Class; #Automatically sets @ISA

Most of you are probably cringing right now. I know in the past I have actually used this pattern and gotten slapped on the wrist for it (rightly so). But this is essentially what we are doing with our current exporters.

This has lead to many tools to try and work around the madness. We have several Exporter alternatives, some provide an alternate way of specifying exports, some provide better features for the importer, and some do both. What if you like Exporter::Declare's interface for creating an exporter, but much prefer Sub::Exporter's interface on the importing side? Tough luck, pick one. We don't have this problem when picking between 'parent' and 'base' for subclassing.

We CAN fix this problem. We need to separate our concerns.

Part 1: Meet Importer

I have uploaded the Importer module on cpan. This module acts on behalf of the consumer of exports. Instead of

use Carp qw/croak/;


use Importer 'Carp' => qw/croak/;

What this does is turn Exporter into a specification for declaring that a module has exports. Subclassing Exporter, or importing its import() method are no longer required though. Importer is 100% compatible with all current Exporter features and variables. Because of this you can now have a module that specifies exports, but does not have an import() method, or has an import() method that does something else completely.

Importer has 0 non-core dependencies. Even core dependencies are used sparingly. The only use/require statements it contains are for strict, warnings or to load the module that has the exports (on demand).

The Importer module also has a hook that should allow most other exporter modules on cpan to make themselves compatible with it. I will update Exporter::Declare in the near future. Other exporters will NOT have to use the package variables Exporter expects to work with Importer. You can even directly use the hook in your module to specify your exports (it is just a sub you define in the exporting package)

Part 2: Blead Patch?

Note: This part is not essential. I will be perfectly content just having Importer on cpan.

I have a perl-blead patch in the works that puts Importer into blead, further it updates Exporter in the following ways:

  • The code is a lot cleaner, and a lot smaller
  • There is no longer a complex and confusing caching layer
  • Exporter::Heavy is unnecessary (and mostly empty)
  • Preserves optimal path for simple 1-to-1 sub importing feature
  • Complex importing, or special features are handled via Importer (loaded on demand).
  • Unexpectedly improves performance!

This patch currently causes 1 test failure, and based on a conversation with #p5p it is not likely a real problem, just some large strings that need to be updated (fragile test). That said nobody has touched the test in years and we are not completely sure yet.

I have also tested this change against my canary list of cpan modules, and the current iteration works fine for all of them.

Having Exporter defer to Importer for anything more complex than a 1-to-1 sub import has the benefit that the modules will not grow out of sync. This is helpful, but not required, for maintaining compatibility. It also makes it a lot less likely anyone will ever have to touch Exporter again.

I would also be perfectly happy combining Exporter and Importer into a single dist, and I have no strong opinions for if it would be p5p upstream, or cpan upstream. This depends entirely on what p5p wants to do, they could also just outright reject the proposal.


While working on my Test::Stream/Test2 work I found myself needing the ability to rename subs I imported. This was frustrating as Exporter does not support this feature. In addition the exporters that do are non-core, and not likely to ever be core (Test::Builder can't use non-core modules). I initially solved this by writing my own exporter as part of Test::Stream, but this generated significant negative feedback. Ultimately I was able to get around the problem completely, but I still wanted to solve it as a separate project.

A while back I submitted a proposal and patch to p5p for an enhancement to Exporter. All in all the reception to the idea of the new features was good. There were a lot of opinions on how it should be done, or what side effects there may be, but nobody seemed to outright reject the idea of the features. The things that were brought up really did stick we me though, in particular:

  • Burden of dependency

    To use the new features the consumer is obligated to list the newer Exporter version as a dep, this seems backwards.

  • import() modifying consumers namespace

    Having an exporter work by modifying the consumers namespace seems backwards, we don't have base classes modify a consumer's @INC on import, we have parent and base.

The thread fizzled out partly due to these concerns, partly because the patch did not go far enough in adding the desired features (some people on p5p wanted it to do more), and also a lack of time/energy on my part due to Test2/Test-Stream work. Lately I had some spare time, and I decided to come back to this problem from this new angle.