Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Birth of the [Test::ChangesHasContent] plugin.

  • Loading branch information...
commit 6336f749e48bf292231e1de23a9ba0720b5c0990 1 parent fd2785a
Karen Etheridge authored
21 corpus/DZ_Test_ChangesHasContent/dist.ini
... ... @@ -0,0 +1,21 @@
  1 +name = Foo
  2 +version = 1.23
  3 +author = foobar
  4 +license = Perl_5
  5 +abstract = Test Library
  6 +copyright_holder = foobar
  7 +copyright_year = 2009
  8 +
  9 +[@Filter]
  10 +bundle = @Basic
  11 +remove = ExtraTests
  12 +remove = TestRelease
  13 +remove = ConfirmRelease
  14 +remove = UploadToCPAN
  15 +
  16 +[NextRelease]
  17 +
  18 +[Test::ChangesHasContent]
  19 +
  20 +[FakeRelease]
  21 +
1  corpus/DZ_Test_ChangesHasContent/foobar
... ... @@ -0,0 +1 @@
  1 +this file is meant for testing...
12 corpus/DZ_Test_ChangesHasContent/lib/Foo.pm
... ... @@ -0,0 +1,12 @@
  1 +package Foo;
  2 +use strict;
  3 +use warnings;
  4 +# ABSTRACT: Foo this thing
  5 +
  6 +1;
  7 +
  8 +=head1 DESCRIPTION
  9 +
  10 +Foo the foo.
  11 +
  12 +=cut
134 lib/Dist/Zilla/Plugin/Test/ChangesHasContent.pm
... ... @@ -0,0 +1,134 @@
  1 +use strict;
  2 +use warnings;
  3 +package Dist::Zilla::Plugin::Test::ChangesHasContent;
  4 +
  5 +# ABSTRACT: Release test to ensure Changes has content
  6 +
  7 +# Dependencies
  8 +use Dist::Zilla;
  9 +use autodie 2.00;
  10 +use Moose 0.99;
  11 +use namespace::autoclean 0.09;
  12 +
  13 +# extends, roles, attributes, etc.
  14 +
  15 +extends 'Dist::Zilla::Plugin::InlineFiles';
  16 +with qw/Dist::Zilla::Role::TextTemplate/;
  17 +
  18 +
  19 +has changelog => (
  20 + is => 'ro',
  21 + isa => 'Str',
  22 + default => 'Changes'
  23 +);
  24 +
  25 +around add_file => sub {
  26 + my ($orig, $self, $file) = @_;
  27 + return $self->$orig(
  28 + Dist::Zilla::File::InMemory->new(
  29 + name => $file->name,
  30 + content => $self->fill_in_string($file->content,
  31 + {
  32 + changelog => $self->changelog,
  33 + newver => $self->zilla->version
  34 + }
  35 + )
  36 + )
  37 + );
  38 +};
  39 +
  40 +__PACKAGE__->meta->make_immutable;
  41 +
  42 +1;
  43 +
  44 +__DATA__
  45 +___[ xt/release/check_changes_has_content.t ]___
  46 +#!perl
  47 +
  48 +use Test::More tests => 2;
  49 +
  50 +note 'Checking Changes';
  51 +my $changes_file = '{{$changelog}}';
  52 +my $newver = '{{$newver}}';
  53 +
  54 +SKIP: {
  55 + ok(-e $changes_file, "$changes_file file exists")
  56 + or skip 'Changes is missing', 1;
  57 +
  58 + ok(_get_changes($newver), "$changes_file has content for $newver");
  59 +}
  60 +
  61 +done_testing;
  62 +
  63 +sub _get_changes
  64 +{
  65 + my $newver = shift;
  66 +
  67 + # parse changelog to find commit message
  68 + open(my $fh, '<', $changes_file) or die "cannot open $changes_file: $!";
  69 + my $changelog = join('', <$fh>);
  70 + close $fh;
  71 +
  72 + my @content =
  73 + grep { /^$newver(?:\s+|$)/ ... /^\S/ } # from newver to un-indented
  74 + split /\n/, $changelog;
  75 + shift @content; # drop the version line
  76 +
  77 + # drop unindented last line and trailing blank lines
  78 + pop @content while ( @content && $content[-1] =~ /^(?:\S|\s*$)/ );
  79 +
  80 + # return number of non-blank lines
  81 + return scalar @content;
  82 +}
  83 +
  84 +__END__
  85 +
  86 +=for Pod::Coverage before_release
  87 +
  88 +=begin wikidoc
  89 +
  90 += SYNOPSIS
  91 +
  92 + # in dist.ini
  93 +
  94 + [CheckChangesHasContent]
  95 +
  96 += DESCRIPTION
  97 +
  98 +This is a "before release" Dist::Zilla plugin that ensures that your Changes
  99 +file actually has some content since the last release. If it doesn't find any,
  100 +it will abort the release process.
  101 +
  102 +The algorithm is very naive. It looks for an unindented line starting with
  103 +the version to be released. It then looks for any text from that line until
  104 +the next unindented line (or the end of the file), ignoring whitespace.
  105 +
  106 +For example, in the file below, algorithm will find "- blah blah blah":
  107 +
  108 + Changes file for Foo-Bar
  109 +
  110 + {{$NEXT}}
  111 +
  112 + - blah blah blah
  113 +
  114 + 0.001 Wed May 12 13:49:13 EDT 2010
  115 +
  116 + - the first release
  117 +
  118 +If you had nothing but whitespace between { {{$NEXT}} } and { 0.001 },
  119 +the release would be halted.
  120 +
  121 +If you name your change log something other than "Changes", you can configure
  122 +the name with the {changelog} argument:
  123 +
  124 + [CheckChangesHasContent]
  125 + changelog = ChangeLog
  126 +
  127 += SEE ALSO
  128 +
  129 +* [Dist::Zilla]
  130 +
  131 +=end wikidoc
  132 +
  133 +=cut
  134 +
128 t/test_changeshascontent.t
... ... @@ -0,0 +1,128 @@
  1 +use strict;
  2 +use warnings;
  3 +
  4 +use Test::More 0.88;
  5 +use Dist::Zilla::Tester;
  6 +use Test::Harness;
  7 +use Path::Class;
  8 +use Cwd 'getcwd';
  9 +use IO::Scalar;
  10 +
  11 +my $test_file = file(qw(xt release check_changes_has_content.t));
  12 +my $root = 'corpus/DZ_Test_ChangesHasContent';
  13 +
  14 +sub capture_test_results($)
  15 +{
  16 + my $build_dir = shift;
  17 +
  18 + my $test_file_full = file($build_dir, $test_file)->stringify;
  19 + my $cwd = getcwd;
  20 + chdir $build_dir;
  21 +
  22 + my $output;
  23 + # I'd use TAP::Parser here, except the docs are horrid.
  24 + my @results = Test::Harness::execute_tests(
  25 + tests => [$test_file_full],
  26 + out => IO::Scalar->new(\$output),
  27 + );
  28 + chdir $cwd;
  29 + return @results, $output;
  30 +}
  31 +
  32 +{
  33 + my $tzil = Dist::Zilla::Tester->from_config(
  34 + { dist_root => $root },
  35 + );
  36 + ok($tzil, "created test dist with no Changes file");
  37 +
  38 + $tzil->build_in;
  39 + my ($total, $failed) = capture_test_results($tzil->built_in);
  40 + is($total->{max}, 2, 'two tests planned');
  41 + is($total->{sub_skipped}, 1, 'one test skipped');
  42 + my ($test_name) = keys %$failed;
  43 + is($failed->{$test_name}{canon}, 1, 'the first test failed (Changes file does not exist)');
  44 +}
  45 +
  46 +{
  47 + my $tzil = Dist::Zilla::Tester->from_config(
  48 + { dist_root => $root },
  49 + {
  50 + add_files => {
  51 + 'source/Changes' => <<'END',
  52 +Changes
  53 +
  54 +{{$NEXT}}
  55 +
  56 +END
  57 + },
  58 + },
  59 + );
  60 + ok( $tzil, "created test dist with stub Changes file");
  61 +
  62 + $tzil->build_in;
  63 + my ($total, $failed) = capture_test_results($tzil->built_in);
  64 + is($total->{max}, 2, 'two tests planned');
  65 + is($total->{sub_skipped}, 0, 'no tests skipped');
  66 + is($total->{ok}, 1, 'one test passed');
  67 + my ($test_name) = keys %$failed;
  68 + is($failed->{$test_name}{canon}, 2, 'the second test failed (Changes file has no content)');
  69 +}
  70 +
  71 +{
  72 + my $tzil = Dist::Zilla::Tester->from_config(
  73 + { dist_root => $root },
  74 + {
  75 + add_files => {
  76 + 'source/Changes' => <<'END',
  77 +Changes
  78 +
  79 +{{$NEXT}}
  80 +
  81 +1.22 2010-05-12 00:33:53 EST5EDT
  82 +
  83 + - not really released
  84 +
  85 +END
  86 + },
  87 + },
  88 + );
  89 + ok($tzil, "created test dist with no new Changes");
  90 +
  91 + $tzil->build_in;
  92 + my ($total, $failed) = capture_test_results($tzil->built_in);
  93 + is($total->{max}, 2, 'two tests planned');
  94 + is($total->{sub_skipped}, 0, 'no tests skipped');
  95 + my ($test_name) = keys %$failed;
  96 + is($failed->{$test_name}{canon}, 2, 'the second test failed (Changes file has no content)');
  97 +}
  98 +
  99 +{
  100 + my $tzil = Dist::Zilla::Tester->from_config(
  101 + { dist_root => $root },
  102 + {
  103 + add_files => {
  104 + 'source/Changes' => <<'END',
  105 +Changes
  106 +
  107 +1.23
  108 +
  109 + - this is a change note, I promise
  110 +
  111 +1.22 2010-05-12 00:33:53 EST5EDT
  112 +
  113 + - not really released
  114 +
  115 +END
  116 + },
  117 + },
  118 + );
  119 + ok($tzil, "created test dist with a new Changes entry");
  120 +
  121 + $tzil->build_in;
  122 + my ($total, $failed) = capture_test_results($tzil->built_in);
  123 + is($total->{max}, 2, 'two tests planned');
  124 + is($total->{sub_skipped}, 0, 'no tests skipped');
  125 + is(scalar(keys %$failed), 0, 'no tests failed');
  126 +}
  127 +
  128 +done_testing;

0 comments on commit 6336f74

Please sign in to comment.
Something went wrong with that request. Please try again.