Hi Johan, On Fri, Jul 25, 2014 at 5:08 AM, Johan De Wit <jo...@open-future.be> wrote:
> Hi, > > Does someone knows more rspec code examples for working with files ? > > I stumbled across https://github.com/puppetlabs/puppetlabs-inifile/blob/ > master/spec/unit/puppet/provider/ini_setting/ruby_spec.rb , > > but cannot find more examples, and struggling a bit in writing good rspec > tests for the following code snippet : > > You essentially have two choices when doing this kind of thing: use a real filesystem or stub it out in some way. The code that you pointed to looks to be using a real filesystem. In that case what is often a good practice is to create a temp directory in a setup step (before :each) and delete it in a teardown (after :each). Then you do whatever is needed to have your code read from that directory. In your case it looks like you should also set Puppet[:config] to be some fake file in that directory. Then write out the files that you need for your check (or don't write out the file if you want to test the File.exist? == false paths). If you are going to go down the stubbing route you'll have a much harder time. You can use something like fakefs (a ruby gem for testing against filesystems), but since you are pulling in all of puppet for this you might encounter a lot of problems as it tries to read things that you don't care about at all. If you are going to head down that path, then I suggest extracting your functionality out of the puppet function, test it in isolation, and then make the puppet function a very small adapter to the other code (essentially just a single call). Then you can test your logic without any ties to puppet. > (intention is to read the uid from a yaml file for users) > > require 'yaml' > module Puppet::Parser::Functions > newfunction(:lookup_uid, :type => :rvalue ) do |args| > > # read the configuration file from puppets configuration dir > configfile = File.join([File.dirname(Puppet.settings[:config]), > 'lookup_uid.yaml']) > raise(Puppet::ParseError, "lookup_uid configfile not readable") unless > File.exist?(configfile) > config = YAML.load_file(configfile) > > # read the user yaml file > raise(Puppet::ParseError, "Could not load user mapping file > (#{config['user_file']}") unless File.exists?(config['user_file']) > > # Lookup the uid, and convert it to an integer > users = YAML.load_file(config['user_file']) > uid = users.fetch(args[0], ifnone = nil) > raise(Puppet::ParseError, "#{args[0]} user not found in > #{config['user_file']}") unless uid > uid.to_int > end > end > > In the code itself there are a few things that caught my eye. Your tests might have uncovered some of these. require 'yaml' # no need to open the module, just call the function # you can use arity to have it do some parameter checks for you (assuming it'll be used on a new enough puppet) Puppet::Parser::Functions.newfunction(:lookup_uid, :type => :rvalue, :arity => 1) do |args| # give the parameter a meaningful name as soon as possible username = args[0] # don't need to construct an array in the join() call # also, why :config and not :confdir? # Settings can be accessed by just using Puppet[:settingname] instead of Puppet.settings[:settingname] configfile = File.join(File.dirname(Puppet[:config]), 'lookup_uid.yaml') # I always prefer stating things in the positive and using a full if ... else ... end. I find that it makes the various code paths and error cases much more visible. if File.exist?(configfile) # this can raise errors, you might consider dealing with them here and providing some context to the user in the error message, just don't lose the original error! config = YAML.load_file(configfile) # once again, prefer positive statements # config could be nil, and 'user_file' could be nil (or not a string) # there are actually more ways that this could be validated...isn't input validation fun? if config.is_a?(Hash) && config['user_file'].is_a?(String) && File.exists?(config['user_file']) users = YAML.load_file(config['user_file']) # passing nil in the second position to fetch() is the same as just fetching and getting nothing (since it is the default) uid = users[username] if uid # adding some error checking around this might be good. It is possible that it can't be converted to an int uid.to_int else raise(Puppet::ParseError, "#{username} user not found in #{config['user_file']}") end else # with all of the extra validation above, it is clear that this isn't enough of an error message, in fact the validation might be something to do as a separate step and be able to signal each possible error individually raise(Puppet::ParseError, "Could not load user mapping file (#{config['user_file']}") end else # In errors be as precise and convey as much information as possible. In this case, what file did it look for. Also, the check was for existence, so you can only inform the user about that state of things. raise(Puppet::ParseError, "lookup_uid configfile #{configfile} does not exist") end end > Thxs > > johan > > -- > Johan De Wit > > Open Source Consultant > > Red Hat Certified Engineer (805008667232363) > Puppet Certified Professional 2013/2014 (PCP0000006) > _________________________________________________________ > Open-Future Phone +32 (0)2/255 70 70 > Zavelstraat 72 Fax +32 (0)2/255 70 71 > 3071 KORTENBERG Mobile +32 (0)474/42 40 73 > BELGIUM http://www.open-future.be > _________________________________________________________ > > Next Events: > Linux Training | https://www.open-future.be/linux-training-8-till-12th- > september > Puppet Introduction Course | https://www.open-future.be/ > puppet-introduction-course-15th-september > Puppet Fundamentals Training | https://www.open-future.be/ > puppet-fundamentals-training-16-till-18th-september Zabbix Certified > Specialist | https://www.open-future.be/zabbix-certified- > specialisttraining-22-till-24th-september > Zabbix Certified Professional | https://www.open-future.be/ > zabbix-certified-professional-training-25-till-26th-september > Subscribe to our newsletter | http://eepurl.com/BUG8H > > -- > 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+unsubscr...@googlegroups.com. > To view this discussion on the web visit https://groups.google.com/d/ > msgid/puppet-dev/53D248D8.9020304%40open-future.be. > For more options, visit https://groups.google.com/d/optout. > -- Andrew Parker a...@puppetlabs.com Freenode: zaphod42 Twitter: @aparker42 Software Developer *Join us at PuppetConf 2014 <http://www.puppetconf.com/>, September 22-24 in San Francisco* *Register by May 30th to take advantage of the Early Adopter discount <http://links.puppetlabs.com/puppetconf-early-adopter> **—**save $349!* -- 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+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/CANhgQXtapXGjYun92fLqkMZm%2B2OOVqdKpDDUpR5NQqj%2BroYRRA%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.