Re: Can a user cheat and call a class's private method?

2015-05-14 Thread R. Ransbottom
On Tue, May 12, 2015 at 11:03:01PM +0200, Moritz Lenz wrote:

 I'm curious, what's a case where private state of a class needs to be
 tested, and tests agains the public interface are not enough?

 In my experience, testing against private parts only makes the tests
 more brittle (that is, every implementation change causes test failures,
 even if the public interface is unchanged).

Tests are supposed to be brittle so the code is not.

Any routine call could be a good test point--particularly when you need
to change an implementation though the public interface is unchanged.
White box testing has its value.

 Also, are you talking about an actual Perl 6 code base that needs
 testing, but that is too large for a refactoring? If yes, I'd be curious
 where such a beast exists.

The OP was Tom Browder; I was just asking about the merits of 'trust' 
vs.  'augment'.  I have seen code where such testing would be
good, but not yet in Perl 6.

Thanks,
Rob


Re: Can a user cheat and call a class's private method?

2015-05-12 Thread Darren Duncan

On 2015-05-12 12:40 PM, R. Ransbottom wrote:

On Mon, May 11, 2015 at 03:22:46PM -0700, Darren Duncan wrote:


you can use trusts.  Also having to do this may indicate bad code
design. -- Darren Duncan


I saw Moritz' and Carl's responses and I agree with the smell
issue.

Given that the code exists and needs testing, 'augment' seems
preferable to 'trust'.  'augment' avoids the predeclaration
issue and simplifies the test code by removing indirection.

Is class finalization implemented?  Searching the synopses, I
found only a mention.


The other question is whether your private need to be private.

Generally speaking tests should only be against a public interface, and if you 
really need to test something private then maybe a refactoring of the thing 
being tested is in order.


For example splitting it into multiple classes where what was private becomes 
the public API of a utility consumed by the other class.


Any private routines you should be able to test sufficiently indirectly by way 
of public routines that use them, if the code is well organized.


-- Darren Duncan




Re: Can a user cheat and call a class's private method?

2015-05-12 Thread Moritz Lenz
Hi,

On 05/12/2015 09:40 PM, R. Ransbottom wrote:
 On Mon, May 11, 2015 at 03:22:46PM -0700, Darren Duncan wrote:
 
 you can use trusts.  Also having to do this may indicate bad code
 design. -- Darren Duncan
 
 I saw Moritz' and Carl's responses and I agree with the smell
 issue.  
 
 Given that the code exists and needs testing,

I'm curious, what's a case where private state of a class needs to be
tested, and tests agains the public interface are not enough?

In my experience, testing against private parts only makes the tests
more brittle (that is, every implementation change causes test failures,
even if the public interface is unchanged).

Also, are you talking about an actual Perl 6 code base that needs
testing, but that is too large for a refactoring? If yes, I'd be curious
where such a beast exists.

 Is class finalization implemented?

I don't think so.

Cheers,
Moritz


Re: Can a user cheat and call a class's private method?

2015-05-11 Thread Darren Duncan
See Moritz Lenz' response to this thread on March 26.  To summarize, you can use 
trusts.  Also having to do this may indicate bad code design. -- Darren Duncan


On 2015-05-11 2:13 PM, R. Ransbottom wrote:



I need to test some private routines, so is there a way to do that?


Is there a downsize to augment for this?


# source
class Dog {
 method bark { say( #bark); return bark }
 method !pee { say( #pee ); return pee}
}


# test

#use MONKEY_TYPING;
use Test;
use v6;
plan 4;

my Dog $t;

ok( Dog.bark eq  bark, Good loud Dog );
ok( $t.bark eq  bark, Good loud dog );

augment class Dog { # augment should be a test
 # do private tests in private
  ok( Dog!pee eq pee, Good bad Dog );
  ok( $t!pee eq pee, Good bad dog );
}







Re: Can a user cheat and call a class's private method?

2015-03-27 Thread Carl Mäsak
This feels like the same conversation we had earlier this week about
accessing private methods. :) But maybe there are still a few new
points that can be made.

Tom (), Moritz ():
 I need to test some private routines, so is there a way to do that?

 The easiest way to do that is when the class with the private methods
 trusts the class that calls them. See for example
 http://doc.perl6.org/type/Metamodel::Trusting
 http://design.perl6.org/S12.html#Trusts
 https://github.com/perl6/roast/blob/master/S12-attributes/trusts.t

I would consider all usages of `trusts` a code smell, if nothing else
than for the reason that it links your upstream producer (your class)
to a downstream producer (your tests), and explicitly talking about
something downstream creates an unholy coupling to it, *and* is
difficult because you have to predeclare it in some way.

 But you should ask yourself if you really, really want this.

 And then you can also do something like:

 my $private_method = $obj.^private_method_table{$methodname};
 $obj.$private_metnod(arguments here)

 but it is rather questionable use of the MOP.

I would actually use $obj.^find_private_method, as I showed in that
other thread:

class C { method !foo { say OH HAI } }; my $obj = C.new; my $pm
= C.^find_private_method(foo); $obj.$pm

But I would also amend moritz' rather questionable by saying that if
you do this, even from the comfort of your own tests, you waive
certain advantages of good OOP that you then won't get back.

That little '^' means time to cheat -- if private methods are the
walls of a labyrinth preventing you from going wrong, the '^' just
took you to cheat mode and you can survey the whole labyrinth from
above. In my opinion, tests shouldn't have to resort to that. A very
small list of things require cheat mode. Tests don't.

The reason we deal with all this inside/outside stuff and make some
things private, is so that we can reserve the right to evolve them
without breaking anything on the outside. Like a
https://en.wikipedia.org/wiki/Ball_bearing, the insides are supposed
to be able to move without creating any friction on the outside.

Any kind of coupling with the outside makes that kind of frictionless
evolution harder. Going to the MOP to break the privacy couples the
tests to the implementation.

Beyond that, this simply *shouldn't need to happen* if the tests are
written by the same person as the implementation.

(A) Either you need to test the method, and then it can happily be
made public, or be made an our sub, or a sub outside of the class.
(B) Or you keep the method private, but find some other way to test it
besides calling it directly.

The goal here is to write tests that don't break in the future. In a
way, this is what good OOP leads to. Coupling your tests to private
methods is a mistake, IMHO. Perl 6 makes this difficult because it's
not a good idea.

// Carl


Re: Can a user cheat and call a class's private method?

2015-03-27 Thread Tom Browder
On Fri, Mar 27, 2015 at 6:36 AM, Carl Mäsak cma...@gmail.com wrote:
 This feels like the same conversation we had earlier this week about
 accessing private methods. :) But maybe there are still a few new
 points that can be made.
...

Okay, Carl, I think I understand.  But what about this for my
particular situation (this sounds like your method A I believe):

Use a separate module (but included with the code for the whole
package) for the non-class-specific, formerly-private methods to be
public, but the use statement for the modules would be inside the
class-specific methods that need them (a new, restricted scoping in
Perl 6 I understand).

That actually makes more sense to me now because some of the private
methods are really general math subroutines.  That way I can test
those subroutines without breaking OOP (I think).

Best,

-Tom


Re: Can a user cheat and call a class's private method?

2015-03-27 Thread yary
On Fri, Mar 27, 2015 at 8:35 AM, Tom Browder tom.brow...@gmail.com wrote:
 Use a separate module (but included with the code for the whole
 package) for the non-class-specific, formerly-private methods to be
 public,  because some of the private
 methods are really general math subroutines.  That way I can test
 those subroutines without breaking OOP (I think).

That's a double win, both making the larger module better organized
and creating a new module of general utility.

 the use statement for the modules would be inside the
 class-specific methods that need them (a new, restricted scoping in
 Perl 6 I understand).

Hmm, I never thought about the scoping of use in Perl 5, but that
makes sense- exports in Perl 5 are into the namespace of the current
package, not lexical- though a package declaration is lexical. Learn
something new every day

-y


Re: Can a user cheat and call a class's private method?

2015-03-26 Thread Tom Browder
On Mar 26, 2015 11:04 AM, Moritz Lenz mor...@faui2k3.org wrote:
 On 26.03.2015 16:55, Tom Browder wrote:
  I need to test some private routines, so is there a way to do that
...
 And then you can also do something like:

 my $private_method = $obj.^private_method_table{$methodname};
 $obj.$private_metnod(arguments here)

That works great!

 but it is rather questionable use of the MOP.

Nevertheless, it is very helpful for debugging.

Thanks.

Cheers!

-Tom


Can a user cheat and call a class's private method?

2015-03-26 Thread Tom Browder
I need to test some private routines, so is there a way to do that?

Or will I have to copy code to a test script or?

BTW, the tests are for input/output checks during development--not for
the public user.

Thanks.

Best,

-Tom