use Test::More;
use App::PAIA::Tester;
new_paia_test;
paia qw(config);
is stdout, "{}\n";
is error, undef;
paia qw(config -c x.json --verbose);
is error, "failed to open config file x.json\n";
ok exit_code;
paia qw(config --config x.json --verbose foo bar);
is output, "# saved config file x.json\n";
paia qw(config foo bar);
paia qw(config base http://example.org/);
is exit_code, 0;
is output, '';
paia qw(config);
is_deeply stdout_json, {
base => 'http://example.org/',
foo => 'bar',
}, "get full config"
done_paia_test;
The application is called paia
- that's how it called at command line and that's how it is simply called as function in the tests. The wrapper class (here: App::PAIA::Tester) creates a singleton App::Cmd::Tester::Result object and exports its methods (stdout
, stderr
, exit_code
...). This alone makes the test much more readable. The wrapper further exports two methods to set up a testing environment (new_paia_test
) and to finish testing (done_paia_test
). In my case the setup creates an empty temporary directory, other applications might clean up environment variables etc. Depending on your application you might also add some handy functions like stdout_json
to parse the app's output in a form that can better be tested.
Common schema-less approaches to XML processing in Perl seem to use XML-LibXML, to get a full XML DOM or a stream of parsing events, or XML::Simple (better used as XML::LibXML::Simple. XML::Simple transforms between XML and Perl data structures but it was designed for "data-oriented" XML where element order does not matter a lot. With XML::Struct I created something like XML::Simple for "document-oriented" XML.
]]> While XML::Simple returns uses (or hashes of arrays when elements are repeated), XML::Struct uses arrays for representing XML data. This is best illustrated by an example:<root>
<foo>text</foo>
<bar key="value"> <!-- mixed content here: -->
text
<doz/>
</bar>
</root>
is transformed to this structure:
[
root => { }, [
[ foo => { }, "text" ],
[ bar => { key => "value" }, [
"text",
[ doz => { } ]
]
]
]
XML Attributes are transformed to hashes, that can also be omitted with attributes => 0
. If you still want a key-value structure for (parts of) a document, use hashifyXML
. The distribution contains methods for both parsing, and serializing based on XML::LibXML. XML is processed as stream, so one can also extract chunks from very large XML files.
Comments, bug reports, extensions etc. are welcome, especially at https://github.com/nichtich/XML-Struct.
]]>So "Pumkin Perl" should be Perl>=5.14 (with "should" in the sense of RFC 2119). This notion does not cost anything but helps to assume modern features such as "say", "//", and "given".
]]>vars
you configure it with. Many middlewares add or modify "secondary" parts of the request, for instance Plack::Middleware::SimpleLogger modifies psgix.logger
. I'd say that the "core" request is build of all uppercase env keys listed in the PSGI spec plus psgi.url_scheme
and psgi.input
only.
Sure the classification is only one dimension to organize middlewares. I does not tell why or how the request and/or response are passed, modified or routed, but it should be enough to create a nice railroad diagram of your PSGI stack.
]]>By now there are more than 200 PSGI middlewares classes at CPAN. An organized registry of PSGI middleware modules would help. I'd propose the following classification for the primary action that the middleware does to request and response flow:
In my opinion a useful PSGI middleware should concentrate one one simple task instead of building yet another framework. In the last couple of days I added some middleware modules that can be used independently (like all middleware modules) or combined:
The source code of each module is rather short (around one third for code, documentation, and unit tests each) and the modules are quite new. Feedback is welcome, for instance github pull requests or comments how to further simplify.
What do you think about the "the shorter and more focused, the better" approach to creating PSGI middleware modules?
]]>