It is possible to mock / stub a local variable in the module being tested?

1,891 views
Skip to first unread message

James Perry

unread,
Jul 25, 2017, 5:33:10 PM7/25/17
to Puppet Developers
I'm not sure if it can be done, but I am trying to test a case where I take an array of values and use stdlib's delete to remove one value before iterating over it. The class will fail if the removed value is present. That all works fine except I am trying to write an rspec for it. Nothing I have found seems to have a way I can figure out to do this. 

class my_class {
   $var1 = ['a','b','c']
   $var2 = delete($var1, 'b') ==> Now ['a','c']

   $var2.each |$var3| {
      if $var3 == 'b' {
         fail("Found b")    
     }
   }
}

I am trying to mock / stub is before testing do $var2 = ['a','b','c'] to override the calculated $var2 from the delete function. 

What am I missing here?  

I tried let(:vars) {{ var2: ['a','b','c'] }}, which didn't work. 

Did a similar thing with a mock on my_class.new, but the value remained as calculated by the class. 

Is it even possible to stub a local variable to the class / module to force a failure condition? 

Thanks! 

Ryan Whitehurst

unread,
Jul 25, 2017, 5:59:50 PM7/25/17
to puppe...@googlegroups.com
It doesn't make any sense to do this. If the variable is hardcoded, then there's no variation, so there's nothing to test. If the value is supposed to change, then it should be a parameter, not a hardcoded value.

Between this and your previous rspec-puppet question, it appears the approach you're taking to testing is a bit weird. You seem to be trying to test the internals of how the classes work. That's not usually valuable, and frequently difficult, as you've noticed. Instead, think about the inputs a class or module takes and the results it produces.

For your previous question, that's what the answer you got did. The inputs to foo were current_version and installed_version, and then based on those values, the result is either foo::cleanup was included in the catalog or it wasn't, so that's what you were recommended to test.

For this, as written, there are no inputs, so your test would only have one condition: the class compiles. If $var1 is actually an input, either via a class parameter or a fact, then the result is either the catalog compiles or it fails with the specified error message, so you'd test by varying the input value and checking that it failed or compiled, as appropriate.

Remember, tests are there to make sure that the code works as expected. The implementation details don't matter, just the behavior. If you try to test the implementation details, you're doing work that doesn't provide much value and makes it harder to refactor later.
 
Thanks! 

--
You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/10220b50-b89d-46a4-8a8f-b1cbfac87f2a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

James Perry

unread,
Jul 25, 2017, 6:15:34 PM7/25/17
to Puppet Developers
So I am over thinking it then.  I'm taking fact values from a list of installed directories and removing the one matching the current version. This is being used to remove the old install directories and I didn't want it to whack the current version. I wanted to test that having the local variable set to the current version causes the code to error out. Probably not something that I need to test it seems. All of the versions come in via a fact and are compared to the current version. 

I appreciate the input. I have the other tests for including the associated modules to do the tasks testing out fine. 
Thanks! 
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+...@googlegroups.com.

Ryan Whitehurst

unread,
Jul 25, 2017, 6:28:53 PM7/25/17
to puppe...@googlegroups.com
On Tue, Jul 25, 2017 at 3:15 PM, James Perry <jjpe...@gmail.com> wrote:
So I am over thinking it then.  I'm taking fact values from a list of installed directories and removing the one matching the current version. This is being used to remove the old install directories and I didn't want it to whack the current version. I wanted to test that having the local variable set to the current version causes the code to error out. Probably not something that I need to test it seems. All of the versions come in via a fact and are compared to the current version. 

I appreciate the input. I have the other tests for including the associated modules to do the tasks testing out fine. 


Yeah, in that case the most appropriate thing to test is just that it's not trying to remove the current directory (e.g., no file resource ensure=absent for the current directory or whatever the mechanism is). The specific implementation isn't really important, and that means, for example, you could change it in some way so that it doesn't use the intermediate variable without having to change the test.
 
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/30121405-aa03-40ad-a22a-118bca58c260%40googlegroups.com.

James Perry

unread,
Jul 26, 2017, 9:54:59 AM7/26/17
to Puppet Developers
That is the direction I am heading.  I think I will change the class logic to check the size of the array before and after the delete to know if the current version is part of the set or not. Then I can take it from there and well as test that it has X file removes based on the versions it should remove and not the current version.  

Writing spec files is definitely a different way of thinking. I am trying to do proper TDD and write the tests first and then the code, but failing miserably it seems... But I am learning so that is very important as well. 
Reply all
Reply to author
Forward
0 new messages