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

#initialize(root_dir) ⇒ Unit

Returns a new instance of Unit.



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

def initialize(root_dir)
  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.



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

def test_root
  @test_root
end

#tested_cookbookObject (readonly)

This cookbook.



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

def tested_cookbook
  @tested_cookbook
end

Instance Method Details

#frameworkObject



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

def framework
  'chefspec'
end

#generate(recipe_resources = {}) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/chef-umami/test/unit.rb', line 88

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)
  write_spec_helper
  test_files_written << spec_helper_path

  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



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

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

#spec_helper_pathObject



41
42
43
# File 'lib/chef-umami/test/unit.rb', line 41

def spec_helper_path
  File.join(test_root, '..', 'spec_helper.rb')
end

#test_file(recipe = '') ⇒ Object



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

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

#write_spec_helperObject



54
55
56
57
58
59
# File 'lib/chef-umami/test/unit.rb', line 54

def write_spec_helper
  content = ["require '#{framework}'"]
  content << "require '#{framework}/policyfile'"
  content << "at_exit { ChefSpec::Coverage.report! }\n"
  write_file(spec_helper_path, content.join("\n"))
end

#write_test(resource = nil) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/chef-umami/test/unit.rb', line 61

def write_test(resource = nil)
  state_attrs = [] # Attribute hash to be used with #with()
  resource.state_for_resource_reporter.each do |attr, value|
    next if value.nil? || (value.respond_to?(:empty) && 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