fix punctuation
[gitmo/Moose.git] / t / roles / role_conflict_detection.t
CommitLineData
db1ab48d 1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
a28e50e4 6use Test::More;
b10dde3a 7use Test::Fatal;
db1ab48d 8
db1ab48d 9=pod
10
11Mutually recursive roles.
12
13=cut
14
15{
16 package Role::Foo;
db1ab48d 17 use Moose::Role;
18
19 requires 'foo';
d03bd989 20
db1ab48d 21 sub bar { 'Role::Foo::bar' }
d03bd989 22
db1ab48d 23 package Role::Bar;
db1ab48d 24 use Moose::Role;
d03bd989 25
db1ab48d 26 requires 'bar';
d03bd989 27
28 sub foo { 'Role::Bar::foo' }
db1ab48d 29}
30
31{
32 package My::Test1;
db1ab48d 33 use Moose;
d03bd989 34
b10dde3a 35 ::is( ::exception {
db1ab48d 36 with 'Role::Foo', 'Role::Bar';
b10dde3a 37 }, undef, '... our mutually recursive roles combine okay' );
d03bd989 38
db1ab48d 39 package My::Test2;
db1ab48d 40 use Moose;
d03bd989 41
b10dde3a 42 ::is( ::exception {
db1ab48d 43 with 'Role::Bar', 'Role::Foo';
b10dde3a 44 }, undef, '... our mutually recursive roles combine okay (no matter what order)' );
db1ab48d 45}
46
47my $test1 = My::Test1->new;
48isa_ok($test1, 'My::Test1');
49
50ok($test1->does('Role::Foo'), '... $test1 does Role::Foo');
51ok($test1->does('Role::Bar'), '... $test1 does Role::Bar');
52
53can_ok($test1, 'foo');
54can_ok($test1, 'bar');
55
56is($test1->foo, 'Role::Bar::foo', '... $test1->foo worked');
57is($test1->bar, 'Role::Foo::bar', '... $test1->bar worked');
58
59my $test2 = My::Test2->new;
60isa_ok($test2, 'My::Test2');
61
62ok($test2->does('Role::Foo'), '... $test2 does Role::Foo');
63ok($test2->does('Role::Bar'), '... $test2 does Role::Bar');
64
65can_ok($test2, 'foo');
66can_ok($test2, 'bar');
67
68is($test2->foo, 'Role::Bar::foo', '... $test2->foo worked');
69is($test2->bar, 'Role::Foo::bar', '... $test2->bar worked');
70
71# check some meta-stuff
72
73ok(Role::Foo->meta->has_method('bar'), '... it still has the bar method');
74ok(Role::Foo->meta->requires_method('foo'), '... it still has the required foo method');
75
76ok(Role::Bar->meta->has_method('foo'), '... it still has the foo method');
77ok(Role::Bar->meta->requires_method('bar'), '... it still has the required bar method');
78
79=pod
80
81Role method conflicts
82
83=cut
84
85{
86 package Role::Bling;
db1ab48d 87 use Moose::Role;
d03bd989 88
db1ab48d 89 sub bling { 'Role::Bling::bling' }
d03bd989 90
db1ab48d 91 package Role::Bling::Bling;
db1ab48d 92 use Moose::Role;
d03bd989 93
94 sub bling { 'Role::Bling::Bling::bling' }
db1ab48d 95}
96
97{
98 package My::Test3;
db1ab48d 99 use Moose;
d03bd989 100
b10dde3a 101 ::like( ::exception {
db1ab48d 102 with 'Role::Bling', 'Role::Bling::Bling';
b10dde3a 103 }, qr/Due to a method name conflict in roles 'Role::Bling' and 'Role::Bling::Bling', the method 'bling' must be implemented or excluded by 'My::Test3'/, '... role methods conflict and method was required' );
d03bd989 104
db1ab48d 105 package My::Test4;
db1ab48d 106 use Moose;
d03bd989 107
b10dde3a 108 ::is( ::exception {
db1ab48d 109 with 'Role::Bling';
f6bee6fe 110 with 'Role::Bling::Bling';
b10dde3a 111 }, undef, '... role methods didnt conflict when manually combined' );
d03bd989 112
db1ab48d 113 package My::Test5;
db1ab48d 114 use Moose;
d03bd989 115
b10dde3a 116 ::is( ::exception {
db1ab48d 117 with 'Role::Bling::Bling';
f6bee6fe 118 with 'Role::Bling';
b10dde3a 119 }, undef, '... role methods didnt conflict when manually combined (in opposite order)' );
d03bd989 120
db1ab48d 121 package My::Test6;
db1ab48d 122 use Moose;
d03bd989 123
b10dde3a 124 ::is( ::exception {
db1ab48d 125 with 'Role::Bling::Bling', 'Role::Bling';
b10dde3a 126 }, undef, '... role methods didnt conflict when manually resolved' );
d03bd989 127
db1ab48d 128 sub bling { 'My::Test6::bling' }
24817476 129
130 package My::Test7;
131 use Moose;
132
133 ::is( ::exception {
134 with 'Role::Bling::Bling', { -excludes => ['bling'] }, 'Role::Bling';
135 }, undef, '... role methods didnt conflict when one of the conflicting methods is excluded' );
136
137 package My::Test8;
138 use Moose;
139
140 ::is( ::exception {
141 with 'Role::Bling::Bling', { -excludes => ['bling'], -alias => { bling => 'bling_bling' } }, 'Role::Bling';
142 }, undef, '... role methods didnt conflict when one of the conflicting methods is excluded and aliased' );
db1ab48d 143}
144
145ok(!My::Test3->meta->has_method('bling'), '... we didnt get any methods in the conflict');
146ok(My::Test4->meta->has_method('bling'), '... we did get the method when manually dealt with');
147ok(My::Test5->meta->has_method('bling'), '... we did get the method when manually dealt with');
148ok(My::Test6->meta->has_method('bling'), '... we did get the method when manually dealt with');
24817476 149ok(My::Test7->meta->has_method('bling'), '... we did get the method when manually dealt with');
150ok(My::Test8->meta->has_method('bling'), '... we did get the method when manually dealt with');
151ok(My::Test8->meta->has_method('bling_bling'), '... we did get the aliased method too');
db1ab48d 152
d79e62fd 153ok(!My::Test3->does('Role::Bling'), '... our class does() the correct roles');
154ok(!My::Test3->does('Role::Bling::Bling'), '... our class does() the correct roles');
155ok(My::Test4->does('Role::Bling'), '... our class does() the correct roles');
156ok(My::Test4->does('Role::Bling::Bling'), '... our class does() the correct roles');
157ok(My::Test5->does('Role::Bling'), '... our class does() the correct roles');
158ok(My::Test5->does('Role::Bling::Bling'), '... our class does() the correct roles');
159ok(My::Test6->does('Role::Bling'), '... our class does() the correct roles');
160ok(My::Test6->does('Role::Bling::Bling'), '... our class does() the correct roles');
24817476 161ok(My::Test7->does('Role::Bling'), '... our class does() the correct roles');
162ok(My::Test7->does('Role::Bling::Bling'), '... our class does() the correct roles');
163ok(My::Test8->does('Role::Bling'), '... our class does() the correct roles');
164ok(My::Test8->does('Role::Bling::Bling'), '... our class does() the correct roles');
d79e62fd 165
db1ab48d 166is(My::Test4->bling, 'Role::Bling::bling', '... and we got the first method that was added');
167is(My::Test5->bling, 'Role::Bling::Bling::bling', '... and we got the first method that was added');
168is(My::Test6->bling, 'My::Test6::bling', '... and we got the local method');
24817476 169is(My::Test7->bling, 'Role::Bling::bling', '... and we got the non-excluded method');
170is(My::Test8->bling, 'Role::Bling::bling', '... and we got the non-excluded/aliased method');
171is(My::Test8->bling_bling, 'Role::Bling::Bling::bling', '... and the aliased method comes from the correct role');
db1ab48d 172
173# check how this affects role compostion
174
175{
176 package Role::Bling::Bling::Bling;
db1ab48d 177 use Moose::Role;
d03bd989 178
db1ab48d 179 with 'Role::Bling::Bling';
d03bd989 180
181 sub bling { 'Role::Bling::Bling::Bling::bling' }
db1ab48d 182}
183
184ok(Role::Bling::Bling->meta->has_method('bling'), '... still got the bling method in Role::Bling::Bling');
d79e62fd 185ok(Role::Bling::Bling->meta->does_role('Role::Bling::Bling'), '... our role correctly does() the other role');
fb1e11d5 186ok(Role::Bling::Bling::Bling->meta->has_method('bling'), '... dont have the bling method in Role::Bling::Bling::Bling');
d03bd989 187is(Role::Bling::Bling::Bling->meta->get_method('bling')->(),
d05cd563 188 'Role::Bling::Bling::Bling::bling',
189 '... still got the bling method in Role::Bling::Bling::Bling');
db1ab48d 190
fb1e11d5 191
db1ab48d 192=pod
193
194Role attribute conflicts
195
196=cut
197
198{
199 package Role::Boo;
db1ab48d 200 use Moose::Role;
d03bd989 201
db1ab48d 202 has 'ghost' => (is => 'ro', default => 'Role::Boo::ghost');
d03bd989 203
db1ab48d 204 package Role::Boo::Hoo;
db1ab48d 205 use Moose::Role;
d03bd989 206
db1ab48d 207 has 'ghost' => (is => 'ro', default => 'Role::Boo::Hoo::ghost');
208}
209
210{
211 package My::Test7;
db1ab48d 212 use Moose;
d03bd989 213
b10dde3a 214 ::like( ::exception {
db1ab48d 215 with 'Role::Boo', 'Role::Boo::Hoo';
b10dde3a 216 }, qr/We have encountered an attribute conflict.+ghost/ );
db1ab48d 217
218 package My::Test8;
db1ab48d 219 use Moose;
220
b10dde3a 221 ::is( ::exception {
db1ab48d 222 with 'Role::Boo';
223 with 'Role::Boo::Hoo';
b10dde3a 224 }, undef, '... role attrs didnt conflict when manually combined' );
d03bd989 225
db1ab48d 226 package My::Test9;
db1ab48d 227 use Moose;
228
b10dde3a 229 ::is( ::exception {
db1ab48d 230 with 'Role::Boo::Hoo';
231 with 'Role::Boo';
b10dde3a 232 }, undef, '... role attrs didnt conflict when manually combined' );
db1ab48d 233
234 package My::Test10;
db1ab48d 235 use Moose;
d03bd989 236
237 has 'ghost' => (is => 'ro', default => 'My::Test10::ghost');
238
b10dde3a 239 ::like( ::exception {
db1ab48d 240 with 'Role::Boo', 'Role::Boo::Hoo';
b10dde3a 241 }, qr/We have encountered an attribute conflict/, '... role attrs conflict and cannot be manually disambiguted' );
db1ab48d 242
243}
244
245ok(!My::Test7->meta->has_attribute('ghost'), '... we didnt get any attributes in the conflict');
246ok(My::Test8->meta->has_attribute('ghost'), '... we did get an attributes when manually composed');
247ok(My::Test9->meta->has_attribute('ghost'), '... we did get an attributes when manually composed');
248ok(My::Test10->meta->has_attribute('ghost'), '... we did still have an attribute ghost (conflict does not mess with class)');
249
d79e62fd 250ok(!My::Test7->does('Role::Boo'), '... our class does() the correct roles');
251ok(!My::Test7->does('Role::Boo::Hoo'), '... our class does() the correct roles');
252ok(My::Test8->does('Role::Boo'), '... our class does() the correct roles');
253ok(My::Test8->does('Role::Boo::Hoo'), '... our class does() the correct roles');
254ok(My::Test9->does('Role::Boo'), '... our class does() the correct roles');
255ok(My::Test9->does('Role::Boo::Hoo'), '... our class does() the correct roles');
256ok(!My::Test10->does('Role::Boo'), '... our class does() the correct roles');
257ok(!My::Test10->does('Role::Boo::Hoo'), '... our class does() the correct roles');
258
db1ab48d 259can_ok('My::Test8', 'ghost');
260can_ok('My::Test9', 'ghost');
261can_ok('My::Test10', 'ghost');
262
263is(My::Test8->new->ghost, 'Role::Boo::ghost', '... got the expected default attr value');
264is(My::Test9->new->ghost, 'Role::Boo::Hoo::ghost', '... got the expected default attr value');
265is(My::Test10->new->ghost, 'My::Test10::ghost', '... got the expected default attr value');
266
d05cd563 267=pod
268
269Role override method conflicts
270
271=cut
272
0558683c 273{
274 package Role::Plot;
275 use Moose::Role;
d03bd989 276
0558683c 277 override 'twist' => sub {
278 super() . ' -> Role::Plot::twist';
279 };
d03bd989 280
0558683c 281 package Role::Truth;
282 use Moose::Role;
d03bd989 283
0558683c 284 override 'twist' => sub {
285 super() . ' -> Role::Truth::twist';
286 };
287}
288
289{
290 package My::Test::Base;
291 use Moose;
d03bd989 292
0558683c 293 sub twist { 'My::Test::Base::twist' }
d03bd989 294
0558683c 295 package My::Test11;
296 use Moose;
d03bd989 297
0558683c 298 extends 'My::Test::Base';
299
b10dde3a 300 ::is( ::exception {
0558683c 301 with 'Role::Truth';
b10dde3a 302 }, undef, '... composed the role with override okay' );
d03bd989 303
0558683c 304 package My::Test12;
305 use Moose;
306
307 extends 'My::Test::Base';
308
b10dde3a 309 ::is( ::exception {
0558683c 310 with 'Role::Plot';
b10dde3a 311 }, undef, '... composed the role with override okay' );
d03bd989 312
0558683c 313 package My::Test13;
314 use Moose;
315
b10dde3a 316 ::isnt( ::exception {
d03bd989 317 with 'Role::Plot';
b10dde3a 318 }, undef, '... cannot compose it because we have no superclass' );
d03bd989 319
0558683c 320 package My::Test14;
321 use Moose;
322
323 extends 'My::Test::Base';
324
b10dde3a 325 ::like( ::exception {
d03bd989 326 with 'Role::Plot', 'Role::Truth';
b10dde3a 327 }, qr/Two \'override\' methods of the same name encountered/, '... cannot compose it because we have no superclass' );
0558683c 328}
329
330ok(My::Test11->meta->has_method('twist'), '... the twist method has been added');
331ok(My::Test12->meta->has_method('twist'), '... the twist method has been added');
332ok(!My::Test13->meta->has_method('twist'), '... the twist method has not been added');
333ok(!My::Test14->meta->has_method('twist'), '... the twist method has not been added');
334
335ok(!My::Test11->does('Role::Plot'), '... our class does() the correct roles');
336ok(My::Test11->does('Role::Truth'), '... our class does() the correct roles');
337ok(!My::Test12->does('Role::Truth'), '... our class does() the correct roles');
338ok(My::Test12->does('Role::Plot'), '... our class does() the correct roles');
339ok(!My::Test13->does('Role::Plot'), '... our class does() the correct roles');
340ok(!My::Test14->does('Role::Truth'), '... our class does() the correct roles');
341ok(!My::Test14->does('Role::Plot'), '... our class does() the correct roles');
342
343is(My::Test11->twist(), 'My::Test::Base::twist -> Role::Truth::twist', '... got the right method return');
344is(My::Test12->twist(), 'My::Test::Base::twist -> Role::Plot::twist', '... got the right method return');
345ok(!My::Test13->can('twist'), '... no twist method here at all');
346is(My::Test14->twist(), 'My::Test::Base::twist', '... got the right method return (from superclass)');
347
348{
349 package Role::Reality;
350 use Moose::Role;
351
b10dde3a 352 ::like( ::exception {
0558683c 353 with 'Role::Plot';
b10dde3a 354 }, qr/A local method of the same name as been found/, '... could not compose roles here, it dies' );
0558683c 355
356 sub twist {
357 'Role::Reality::twist';
358 }
d03bd989 359}
0558683c 360
361ok(Role::Reality->meta->has_method('twist'), '... the twist method has not been added');
fb1e11d5 362#ok(!Role::Reality->meta->does_role('Role::Plot'), '... our role does() the correct roles');
d03bd989 363is(Role::Reality->meta->get_method('twist')->(),
364 'Role::Reality::twist',
0558683c 365 '... the twist method returns the right value');
3c5fd53a 366
f0916ad8 367# Ovid's test case from rt.cpan.org #44
368{
369 package Role1;
370 use Moose::Role;
371
372 sub foo {}
373}
374{
375 package Role2;
376 use Moose::Role;
377
378 sub foo {}
379}
380{
381 package Conflicts;
382 use Moose;
383
b10dde3a 384 ::like( ::exception {
f0916ad8 385 with qw(Role1 Role2);
b10dde3a 386 }, qr/Due to a method name conflict in roles 'Role1' and 'Role2', the method 'foo' must be implemented or excluded by 'Conflicts'/ );
f0916ad8 387}
388
3c5fd53a 389=pod
390
391Role conflicts between attributes and methods
392
21716c07 393[15:23] <kolibrie> when class defines method and role defines method, class wins
394[15:24] <kolibrie> when class 'has' method and role defines method, class wins
395[15:24] <kolibrie> when class defines method and role 'has' method, role wins
396[15:24] <kolibrie> when class 'has' method and role 'has' method, role wins
6549b0d1 397[15:24] <kolibrie> which means when class 'has' method and two roles 'has' method, no tiebreak is detected
21716c07 398[15:24] <perigrin> this is with role and has declaration in the exact same order in every case?
399[15:25] <kolibrie> yes
400[15:25] <perigrin> interesting
401[15:25] <kolibrie> that's what I thought
402[15:26] <kolibrie> does that sound like something I should write a test for?
403[15:27] <perigrin> stevan, ping?
404[15:27] <perigrin> I'm not sure what the right answer for composition is.
405[15:27] <perigrin> who should win
406[15:27] <perigrin> if I were to guess I'd say the class should always win.
407[15:27] <kolibrie> that would be my guess, but I thought I would ask to make sure
408[15:29] <stevan> kolibrie: please write a test
409[15:29] <stevan> I am not exactly sure who should win either,.. but I suspect it is not working correctly right now
410[15:29] <stevan> I know exactly why it is doing what it is doing though
411
412Now I have to decide actually what happens, and how to fix it.
413- SL
3c5fd53a 414
415{
416 package Role::Method;
417 use Moose::Role;
d03bd989 418
3c5fd53a 419 sub ghost { 'Role::Method::ghost' }
420
421 package Role::Method2;
422 use Moose::Role;
d03bd989 423
3c5fd53a 424 sub ghost { 'Role::Method2::ghost' }
425
426 package Role::Attribute;
427 use Moose::Role;
d03bd989 428
3c5fd53a 429 has 'ghost' => (is => 'ro', default => 'Role::Attribute::ghost');
430
431 package Role::Attribute2;
432 use Moose::Role;
d03bd989 433
3c5fd53a 434 has 'ghost' => (is => 'ro', default => 'Role::Attribute2::ghost');
435}
436
437{
438 package My::Test15;
439 use Moose;
440
53a4d826 441 ::lives_ok {
3c5fd53a 442 with 'Role::Method';
53a4d826 443 } '... composed the method role into the method class';
3c5fd53a 444
445 sub ghost { 'My::Test15::ghost' }
446
447 package My::Test16;
448 use Moose;
449
53a4d826 450 ::lives_ok {
3c5fd53a 451 with 'Role::Method';
53a4d826 452 } '... composed the method role into the attribute class';
3c5fd53a 453
454 has 'ghost' => (is => 'ro', default => 'My::Test16::ghost');
455
456 package My::Test17;
457 use Moose;
458
53a4d826 459 ::lives_ok {
3c5fd53a 460 with 'Role::Attribute';
53a4d826 461 } '... composed the attribute role into the method class';
3c5fd53a 462
463 sub ghost { 'My::Test17::ghost' }
464
465 package My::Test18;
466 use Moose;
467
53a4d826 468 ::lives_ok {
3c5fd53a 469 with 'Role::Attribute';
53a4d826 470 } '... composed the attribute role into the attribute class';
3c5fd53a 471
472 has 'ghost' => (is => 'ro', default => 'My::Test18::ghost');
473
474 package My::Test19;
475 use Moose;
476
53a4d826 477 ::lives_ok {
3c5fd53a 478 with 'Role::Method', 'Role::Method2';
53a4d826 479 } '... composed method roles into class with method tiebreaker';
3c5fd53a 480
481 sub ghost { 'My::Test19::ghost' }
482
483 package My::Test20;
484 use Moose;
485
53a4d826 486 ::lives_ok {
3c5fd53a 487 with 'Role::Method', 'Role::Method2';
53a4d826 488 } '... composed method roles into class with attribute tiebreaker';
3c5fd53a 489
490 has 'ghost' => (is => 'ro', default => 'My::Test20::ghost');
491
492 package My::Test21;
493 use Moose;
494
53a4d826 495 ::lives_ok {
3c5fd53a 496 with 'Role::Attribute', 'Role::Attribute2';
53a4d826 497 } '... composed attribute roles into class with method tiebreaker';
3c5fd53a 498
499 sub ghost { 'My::Test21::ghost' }
500
501 package My::Test22;
502 use Moose;
503
53a4d826 504 ::lives_ok {
3c5fd53a 505 with 'Role::Attribute', 'Role::Attribute2';
53a4d826 506 } '... composed attribute roles into class with attribute tiebreaker';
3c5fd53a 507
508 has 'ghost' => (is => 'ro', default => 'My::Test22::ghost');
509
510 package My::Test23;
511 use Moose;
512
53a4d826 513 ::lives_ok {
3c5fd53a 514 with 'Role::Method', 'Role::Attribute';
53a4d826 515 } '... composed method and attribute role into class with method tiebreaker';
3c5fd53a 516
517 sub ghost { 'My::Test23::ghost' }
518
519 package My::Test24;
520 use Moose;
521
53a4d826 522 ::lives_ok {
3c5fd53a 523 with 'Role::Method', 'Role::Attribute';
53a4d826 524 } '... composed method and attribute role into class with attribute tiebreaker';
3c5fd53a 525
526 has 'ghost' => (is => 'ro', default => 'My::Test24::ghost');
527
528 package My::Test25;
529 use Moose;
530
53a4d826 531 ::lives_ok {
3c5fd53a 532 with 'Role::Attribute', 'Role::Method';
53a4d826 533 } '... composed attribute and method role into class with method tiebreaker';
3c5fd53a 534
535 sub ghost { 'My::Test25::ghost' }
536
537 package My::Test26;
538 use Moose;
539
53a4d826 540 ::lives_ok {
3c5fd53a 541 with 'Role::Attribute', 'Role::Method';
53a4d826 542 } '... composed attribute and method role into class with attribute tiebreaker';
3c5fd53a 543
544 has 'ghost' => (is => 'ro', default => 'My::Test26::ghost');
545}
546
547my $test15 = My::Test15->new;
548isa_ok($test15, 'My::Test15');
549is($test15->ghost, 'My::Test15::ghost', '... we access the method from the class and ignore the role method');
550
551my $test16 = My::Test16->new;
552isa_ok($test16, 'My::Test16');
553is($test16->ghost, 'My::Test16::ghost', '... we access the attribute from the class and ignore the role method');
554
555my $test17 = My::Test17->new;
556isa_ok($test17, 'My::Test17');
557is($test17->ghost, 'My::Test17::ghost', '... we access the method from the class and ignore the role attribute');
558
559my $test18 = My::Test18->new;
560isa_ok($test18, 'My::Test18');
561is($test18->ghost, 'My::Test18::ghost', '... we access the attribute from the class and ignore the role attribute');
562
563my $test19 = My::Test19->new;
564isa_ok($test19, 'My::Test19');
565is($test19->ghost, 'My::Test19::ghost', '... we access the method from the class and ignore the role methods');
566
567my $test20 = My::Test20->new;
568isa_ok($test20, 'My::Test20');
569is($test20->ghost, 'My::Test20::ghost', '... we access the attribute from the class and ignore the role methods');
570
571my $test21 = My::Test21->new;
572isa_ok($test21, 'My::Test21');
573is($test21->ghost, 'My::Test21::ghost', '... we access the method from the class and ignore the role attributes');
574
575my $test22 = My::Test22->new;
576isa_ok($test22, 'My::Test22');
577is($test22->ghost, 'My::Test22::ghost', '... we access the attribute from the class and ignore the role attributes');
578
579my $test23 = My::Test23->new;
580isa_ok($test23, 'My::Test23');
581is($test23->ghost, 'My::Test23::ghost', '... we access the method from the class and ignore the role method and attribute');
582
583my $test24 = My::Test24->new;
584isa_ok($test24, 'My::Test24');
585is($test24->ghost, 'My::Test24::ghost', '... we access the attribute from the class and ignore the role method and attribute');
586
587my $test25 = My::Test25->new;
588isa_ok($test25, 'My::Test25');
589is($test25->ghost, 'My::Test25::ghost', '... we access the method from the class and ignore the role attribute and method');
590
591my $test26 = My::Test26->new;
592isa_ok($test26, 'My::Test26');
593is($test26->ghost, 'My::Test26::ghost', '... we access the attribute from the class and ignore the role attribute and method');
594
21716c07 595=cut
a28e50e4 596
597done_testing;