This is similar to, but not quite the same as another of my questions: Content checking some, not all, class attributes
I am writing a test to verify the effect of processing on a object. But I can't work out how to get the value of a known set of the object's attributes but test with the same code. Something like the following (which does not work):
class A { has $.a, has $.b, has $.c };
my A $v .=new(:1a, :2b);
for <a b> { ok $v.{$_} > 0 }; # this does not work, but illustrates the intent.
If instead of an object I had used a Hash, then it is easy to get values from the Hash knowing the keys.
At the moment all I can think of is to test each attribute:
ok $v.a > 0;
ok $v.b > 0;
In addition, I don't want to look at ALL the attributes of the object, which is what .^attributes gives me, only some of them.
Attributes of a class can also be accessed using the following built-in methods and functions : getattr() – This function is used to access the attribute of object. hasattr() – This function is used to check if an attribute exist or not. setattr() – This function is used to set an attribute.
Python getattr() function is used to get the value of an object's attribute and if no attribute of that object is found, default value is returned. Basically, returning the default value is the main reason why you may need to use Python getattr() function.
Use class_name dot variable_name to access a class variable from a class method in Python. Use instance to access variables outside the class.
The issue you are encountering – and the reason tests like this are easier with Hash
es than with Class
es – is that you are passing in a Str
when you need to pass in an object. This issue doesn't come up with Hashe
s because (by default), Hash
keys already are strings.
The other important thing to remember is that, technically speaking, there isn't any way to directly access the attributes of a Raku object from outside of the object – Raku does not have public attributes, just attributes you can access from a public accessor method. This may seem like a pedantic distinction, but it's important here: it means that you need a callable Method
object (which is more specific than the "object" I mentioned in the previous paragraph).
As Tyil mentioned in a comment, you can get Raku to dwym with the code for <a b> { ok $v."$_"() > 0 };
. The reason this works is that the final ()
forces Raku to treat the interpolated value of "$_"
as a Callable
, which in this case means a Method
.
However, I'd prefer to be slightly more explicit and use the following syntax:
for $v.^methods.grep({.name ~~ 'a' | 'b'}) { ok $_($v) > 0}
(This takes advantage of the fact that $object.method
and method($object)
are syntactically equivalent).
Note that we have the grep
above because you wanted to test just some of A
's methods. However, even if you want to test all of the methods you added to A
, you may still need the grep to exclude BUILDALL
, which is returned by $v.^methods(:local)
. I haven't figured out whether that is intentional or a bug (it doesn't seem like a local method) and would appreciate anyone's thoughts on that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With