Class: Umami::Test::Unit

Inherits:
Umami::Test show all
Includes:
Helper::FileTools, Helper::OS
Defined in:
lib/chef-umami/test/unit.rb

Instance Attribute Summary collapse

Attributes inherited from Umami::Test

#root_dir

Instance Method Summary collapse

Methods included from Helper::FileTools

#enforce_styling, #write_file

Methods included from Helper::OS

#os

Constructor Details

#initializeUnit

Returns a new instance of Unit.



28
29
30
31
32
# File 'lib/chef-umami/test/unit.rb', line 28

def initialize
  super
  @test_root = File.join(self.root_dir, 'umami', 'unit', 'recipes')
  @tested_cookbook = File.basename(Dir.pwd)
end

Instance Attribute Details

#test_rootObject (readonly)

Returns the value of attribute test_root.



26
27
28
# File 'lib/chef-umami/test/unit.rb', line 26

def test_root
  @test_root
end

#tested_cookbookObject (readonly)

This cookbook.



27
28
29
# File 'lib/chef-umami/test/unit.rb', line 27

def tested_cookbook
  @tested_cookbook
end

Instance Method Details

#frameworkObject



34
35
36
# File 'lib/chef-umami/test/unit.rb', line 34

def framework
  "chefspec"
end

#generate(recipe_resources = {}) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/chef-umami/test/unit.rb', line 78

def generate(recipe_resources = {})
  test_files_written = []
  recipe_resources.each do |canonical_recipe, resources|
    (cookbook, recipe) = canonical_recipe.split('::')
    # Only write unit tests for the cookbook we're in.
    next unless cookbook == tested_cookbook
    content = [preamble(cookbook, recipe)]
    resources.each do |resource|
      content << write_test(resource)
    end
    content << "end"
    test_file_name = test_file(recipe)
    test_file_content = content.join("\n") + "\n"
    write_file(test_file_name, test_file_content)
    test_files_written << test_file_name
  end

  enforce_styling(test_root)

  unless test_files_written.empty?
    puts "Wrote the following unit test files:"
    test_files_written.each do |f|
      puts "\t#{f}"
    end
  end

end

#preamble(cookbook = '', recipe = '') ⇒ Object



42
43
44
45
46
47
48
49
50
# File 'lib/chef-umami/test/unit.rb', line 42

def preamble(cookbook = '', recipe = '')
  "# #{test_file(recipe)} - Originally written by Umami!\n" \
  "\n" \
  "require '#{framework}'\n" \
  "require '#{framework}/policyfile'\n" \
  "\n" \
  "describe '#{cookbook}::#{recipe}' do\n" \
  "let(:chef_run) { ChefSpec::ServerRunner.new(platform: '#{os[:platform]}', version: '#{os[:version]}').converge(described_recipe) }"
end

#test_file(recipe = '') ⇒ Object



38
39
40
# File 'lib/chef-umami/test/unit.rb', line 38

def test_file(recipe = '')
  "#{test_root}/#{recipe}_spec.rb"
end

#write_test(resource = nil) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/chef-umami/test/unit.rb', line 52

def write_test(resource = nil)
  state_attrs = [] # Attribute hash to be used with #with()
  resource.state.each do |attr, value|
    next if value.nil? or (value.respond_to?(:empty) and value.empty?)
    if value.is_a? String
      value = value.gsub("'", "\\\\'") # Escape any single quotes in the value.
    end
    state_attrs << "#{attr}: '#{value}'"
  end
  action = ''
  if resource.action.is_a? Array
    action = resource.action.first
  else
    action = resource.action
  end
  resource_name = resource.name.gsub("'", "\\\\'") # Escape any single quotes in the resource name.
  test_output = ["\nit '#{action}s #{resource.declared_type} \"#{resource_name}\"' do"]
  if state_attrs.empty?
    test_output << "expect(chef_run).to #{action}_#{resource.declared_type}('#{resource_name}')"
  else
    test_output << "expect(chef_run).to #{action}_#{resource.declared_type}('#{resource_name}').with(#{state_attrs.join(', ')})"
  end
  test_output << "end\n"
  test_output.join("\n")
end