Dancer::Test(3pm)
πΈ Dancer::Test πΈ
okay bestie, so this is Dancer::Test, a little helper module that ships with the User Contributed Perl Documentation. It's giving "test your Dancer app without losing your mind" energy, and honestly? Iconic. π
β¨ VERSION β¨
This is version 1.3522 β the one and only. π
π¦ SYNOPSIS π¦
use strict;
use warnings;
use Test::More tests => 2;
use MyWebApp;
use Dancer::Test;
response_status_is [GET => '/'], 200, "GET / is found";
response_content_like [GET => '/'], qr/hello, world/, "content looks good for /";
π DESCRIPTION π
So this module hands you a whole lil' toolkit of test helpers for testing Dancer apps. Slay.
β οΈ Bestie, listen to me. The module loading order in that example up there? SO important. You have touse "Dancer::Test"after you import your application package. Otherwise your appdir gets automatically set toliband your test script literally will not be able to find views, conffiles, and other application content. We do not want that for you. π«Ά
Now, for literally all the test methods, the first argument can be any of these three things:
- an array ref of the method and route,
- a scalar containing just the route β in which case the method is assumed to be
GET, - or a Dancer::Response object.
And the way that they're all the same vibe:
# all 3 are equivalent
response_status_is [ GET => '/' ], 200, 'GET / status is ok';
response_status_is '/', 200, 'GET / status is ok';
my $resp = dancer_response GET => '/';
response_status_is $resp => 200, 'GET / status is ok';
π METHODS π
π route_exists([$method, $path], $test_name)
Asserts that the given request matches a route handler in Dancer's registry. Basically "does this route even exist, or are we delulu?"
route_exists [GET => '/'], "GET / is handled";
π route_doesnt_exist([$method, $path], $test_name)
Asserts that the given request does not match any route handler in Dancer's registry. The opposite vibe entirely.
route_doesnt_exist [GET => '/bogus_path'], "GET /bogus_path is not handled";
π response_exists([$method, $path], $test_name)
π« Deprecated β use response_status_isnt and check for status 404 instead, bestie.
Asserts that a response is found for the given request. And here's the tea: even though a route for that path might not exist, a response can still be found during request processing, because of filters. Plot twist.
response_exists [GET => '/path_that_gets_redirected_to_home'],
"response found for unknown path";
π response_doesnt_exist([$method, $path], $test_name)
π« Deprecated β use response_status_is and check for status 404 instead.
Asserts that no response is found when processing the given request.
response_doesnt_exist [GET => '/unknown_path'],
"response not found for unknown path";
π response_status_is([$method, $path], $status, $test_name)
Asserts that Dancer's response for the given request has a status equal to the one you gave it. No cap.
response_status_is [GET => '/'], 200, "response for GET / is 200";
π response_status_isnt([$method, $path], $status, $test_name)
Asserts that the status of Dancer's response is not equal to the one given. Not today, 404.
response_status_isnt [GET => '/'], 404, "response for GET / is not a 404";
π response_content_is([$method, $path], $expected, $test_name)
Asserts that the response content is equal to the $expected string.
response_content_is [GET => '/'], "Hello, World",
"got expected response content for GET /";
π response_content_isnt([$method, $path], $not_expected, $test_name)
Asserts that the response content is not equal to the $not_expected string.
response_content_isnt [GET => '/'], "Hello, World",
"got expected response content for GET /";
π response_content_is_deeply([$method, $path], $expected_struct, $test_name)
Basically response_content_is(), except if response content and $expected_struct are references, it does a deep comparison β walking each data structure to see if they are equivalent. Like actually checking the whole thing, not just the vibe.
And if the two structures are different, it will show you exactly where they start differing. So helpful. π
response_content_is_deeply [GET => '/complex_struct'],
{ foo => 42, bar => 24},
"got expected response structure for GET /complex_struct";
π response_content_like([$method, $path], $regexp, $test_name)
Asserts that the response content for the given request matches the regexp given.
response_content_like [GET => '/'], qr/Hello, World/,
"response content looks good for GET /";
π response_content_unlike([$method, $path], $regexp, $test_name)
Asserts that the response content for the given request does not match the regexp given.
response_content_unlike [GET => '/'], qr/Page not found/,
"response content looks good for GET /";
π response_headers_are_deeply([$method, $path], $expected, $test_name)
Asserts that the response headers data structure equals the one given. Every header, accounted for, periodt.
response_headers_are_deeply [GET => '/'], [ 'X-Powered-By' => 'Dancer 1.150' ];
π response_headers_include([$method, $path], $expected, $test_name)
Asserts that the response headers data structure includes some of the defined ones. Not all of them β just the ones you care about. Lowkey the chiller version.
response_headers_include [GET => '/'], [ 'Content-Type' => 'text/plain' ];
π response_redirect_location_is([$method, $path], $expected, $test_name)
Asserts that the location header sent with a 302 redirect is equal to the $expected location.
response_redirect_location_is [GET => '/'], 'http://localhost/index.html';
π response_redirect_location_like([$method, $path], $regexp, $test_name)
Asserts that the location header sent with a 302 redirect matches the $regexp provided. Super useful if the redirect location includes a query string. π
response_redirect_location_like [GET => '/'], qr/some_pattern/;
π dancer_response($method, $path, { params => $params, body => $body, headers => $headers, files => [{filename => '/path/to/file', name => 'my_file'}] })
Returns a Dancer::Response object for the given request. Main character behavior, honestly.
Only $method and $path are required. Everything else is up to you, bestie:
$paramsis a hashref$bodycan be a string or a hashref$headerscan be an arrayref or a HTTP::Headers object$filesis an arrayref of hashref, containing some files to upload
$params always populates the query string, even for POST requests. $body always populates the request body. That's just how it is.
π Heads up: currently, Dancer::Test cannot cope with both body and files passed in the same call. Pick one, babes.
A really good reason to use this function is for testing POST requests. Since POST requests may not be idempotent, you need to capture the content and status in one shot. Calling the response_status_is and response_content_is functions in succession would make two requests, each of which could alter the state of the application and cause Schrodinger's cat to die. RIP lil kitty. π
my $response = dancer_response POST => '/widgets';
is $response->{status}, 202, "response for POST /widgets is 202";
is $response->{content}, "Widget #1 has been scheduled for creation",
"response content looks good for first POST /widgets";
$response = dancer_response POST => '/widgets';
is $response->{status}, 202, "response for POST /widgets is 202";
is $response->{content}, "Widget #2 has been scheduled for creation",
"response content looks good for second POST /widgets";
And yes, it's possible to test file uploads too. We love that for us:
post '/upload' => sub { return upload('image')->content };
$response = dancer_response(POST => '/upload', {files => [{name => 'image', filename => '/path/to/image.jpg'}]});
In addition, you can supply the file contents as the "data" key:
my $data = 'A test string that will pretend to be file contents.';
$response = dancer_response(POST => '/upload', {
files => [{name => 'test', filename => "filename.ext", data => $data}]
});
π read_logs
my $logs = read_logs;
Returns an array ref of all log messages issued by the app since the last call to "read_logs".
For example:
warning "Danger! Warning!";
debug "I like pie.";
is_deeply read_logs, [
{ level => "warning", message => "Danger! Warning!" },
{ level => "debug", message => "I like pie.", }
];
error "Put out the light.";
is_deeply read_logs, [
{ level => "error", message => "Put out the light." },
];
See Dancer::Logger::Capture for more details. π
πΈ LICENSE πΈ
This module is free software and is distributed under the same terms as Perl itself. Free as in freedom, bestie. π¦
β AUTHOR β
This module has been written by Alexis Sukrieh <sukria@sukria.net> β¨
π«Ά SEE ALSO π«Ά
- Test::More
π AUTHOR π
Dancer Core Developers π
π COPYRIGHT AND LICENSE π
This software is copyright (c) 2010 by Alexis Sukrieh.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
okay that's the whole page, you ate that π
β¨ this was perl v5.40.1 on 2026-05-05, and every bit of it came from the Dancer::Test(3pm) page under User Contributed Perl Documentation. go write some tests, bestie, you've got this fr fr ππβ
π¦ where this page comes from
- ubuntu stonking: libdancer-perl 1.3522-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms