Class: Pod::Command::Lib::Testing

Inherits:
Pod::Command::Lib show all
Defined in:
lib/pod/command/lib/testing.rb

Overview

TODO:

Create a PR to add your plugin to CocoaPods/cocoapods.org in the ‘plugins.json` file, once your plugin is released.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(argv) ⇒ Testing

Returns a new instance of Testing.



21
22
23
24
25
26
27
28
29
# File 'lib/pod/command/lib/testing.rb', line 21

def initialize(argv)
  @@dry_run = argv.flag?('dry-run')
  @@verbose = argv.flag?('verbose')
  @@args = argv.arguments!

  @@found_projects = []
  @@found_tests = false
  super
end

Class Method Details

.handle_projects_in_dir(dir) ⇒ Object



31
32
33
34
35
36
37
38
# File 'lib/pod/command/lib/testing.rb', line 31

def self.handle_projects_in_dir(dir)
  workspaces_in_dir(dir).each do |workspace_path|
    next if workspace_path.end_with?('.xcworkspace')

    project = Xcodeproj::Project.open(Pathname.new(workspace_path))
    yield project, workspace_path
  end
end

.handle_workspaces_in_dir(dir) ⇒ Object



40
41
42
43
44
45
46
47
# File 'lib/pod/command/lib/testing.rb', line 40

def self.handle_workspaces_in_dir(dir)
  workspaces_in_dir(dir).each do |workspace_path|
    next if workspace_path.end_with?('.xcodeproj')

    workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
    yield workspace, workspace_path
  end
end

.optionsObject



14
15
16
17
18
19
# File 'lib/pod/command/lib/testing.rb', line 14

def self.options
  [
    ['--dry-run', 'Show which tests would be executed.'],
    ['--verbose', 'Show full xcodebuild output.']
  ]
end

.workspaces_in_dir(dir) ⇒ Object

TODO: Refactor to remove all projects which are part of a workspace



152
153
154
155
156
157
158
159
160
# File 'lib/pod/command/lib/testing.rb', line 152

def self.workspaces_in_dir(dir)
  glob_match = Dir.glob("#{dir}/**/*.xc{odeproj,workspace}")
  glob_match = glob_match.reject do |p|
    next true if p.include?('Pods.xcodeproj')
    next true if p.end_with?('.xcodeproj/project.xcworkspace')
    sister_workspace = p.chomp(File.extname(p.to_s)) + '.xcworkspace'
    p.end_with?('.xcodeproj') && glob_match.include?(sister_workspace)
  end
end

Instance Method Details

#handle_project(project, project_location, workspace_location = 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
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/pod/command/lib/testing.rb', line 61

def handle_project(project, project_location, workspace_location = nil)
  return if @@found_projects.include?(project_location)

  schemes = Dir[Xcodeproj::XCScheme.shared_data_dir(project_location).to_s + '/*']
  schemes += Dir[Xcodeproj::XCScheme.user_data_dir(project_location).to_s + '/*']

  scheme_map = Hash.new
  schemes.each do |path|
    next if File.directory?(path)
    doc = REXML::Document.new(File.new(path))
    REXML::XPath.each(doc, '//TestAction') do |action|
      blueprint_name = REXML::XPath.first(action, 
        '//BuildableReference/@BlueprintName').value
      scheme_name = File.basename(path, '.xcscheme')
      scheme_map[blueprint_name] = scheme_name
    end
  end

  project.targets.each do |target|
    product_type = nil

    begin
      product_type = target.product_type.to_s
    rescue
      next
    end

    if product_type.end_with?('bundle.unit-test')
      scheme = scheme_map[target.name]
      # Fallback to first scheme if none is found for this target
      next if not scheme_map.first
      scheme = scheme_map.first[1] unless scheme && scheme.length > 0
      @@found_projects << project_location
      run_tests(workspace_location || project_location, target.name, scheme)
    end
  end
end

#handle_workspace(workspace, workspace_location) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/pod/command/lib/testing.rb', line 99

def handle_workspace(workspace, workspace_location)
  workspace.file_references.each do |ref|
    ref_path = File.absolute_path(ref.path, Pathname.new(workspace_location).dirname)
    if ref_path.end_with?('.xcodeproj')
      if not File.exists? ref_path
        next
      end
      project = Xcodeproj::Project.open(ref_path)
      handle_project(project, ref_path, workspace_location)
    end
  end
end

#handle_xcode_artifacts_in_dir(dir) ⇒ Object



51
52
53
54
55
56
57
58
59
# File 'lib/pod/command/lib/testing.rb', line 51

def handle_xcode_artifacts_in_dir(dir)
  self.class.handle_workspaces_in_dir(dir) do |workspace, workspace_path|
    handle_workspace(workspace, workspace_path)
  end

  self.class.handle_projects_in_dir(dir) do |project, project_path|
    handle_project(project, project_path)
  end
end

#podspecs_to_checkObject



112
113
114
115
116
117
# File 'lib/pod/command/lib/testing.rb', line 112

def podspecs_to_check
  podspecs = Pathname.glob(Pathname.pwd + '*.podspec{.yaml,}')
  msg = 'Unable to find a podspec in the working directory'
  fail Informative, msg if podspecs.count.zero?
  podspecs
end

#runObject



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/pod/command/lib/testing.rb', line 174

def run
  podspecs_to_check.each do # |path|
    # TODO: How to link specs to projects/workspaces?
    # spec = Specification.from_file(path)

    handle_xcode_artifacts_in_dir(Pathname.pwd)

    Dir['*'].each do |dir| 
      next if !File.directory?(dir)
      original_dir = Pathname.pwd
      Dir.chdir(dir)

      handle_xcode_artifacts_in_dir(Pathname.pwd)

      Dir.chdir(original_dir)
    end

    if not @@found_tests
      puts('No suitable test targets found.'.yellow)
      exit(1)
    end
  end
end

#run_tests(workspace, target_name, scheme_name) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/pod/command/lib/testing.rb', line 119

def run_tests(workspace, target_name, scheme_name)
  @@found_tests = true

  XCTasks::TestTask.new do |t|
    t.actions = %w(clean build test)
    t.runner = @@verbose ? :xcodebuild : :xcpretty

    if workspace.end_with? 'workspace'
      t.workspace   = workspace
    else
      t.project = workspace
    end

    t.actions << @@args unless @@args.nil?

    t.subtask(unit: scheme_name) do |s|
      # TODO: version should be configurable
      s.ios_versions = [versions.last]

      # TODO: simulator should be configurable
      if simulators && simulators.count > 0
        s.destination('name='+simulators.first)
      else
        s.destination('name=iPhone Retina (4-inch)')
      end
    end
  end

  UI.puts 'Running tests for ' + target_name
  Rake::Task['test:unit'].invoke unless @@dry_run
end

#simulatorsObject



162
163
164
165
166
# File 'lib/pod/command/lib/testing.rb', line 162

def simulators
  sims = `xcrun simctl list 2>/dev/null`.split("\n")
  sims = sims.select { |sim| sim[/Booted|Shutdown/] }
  sims.map { |sim| sim.gsub(/^\s+(.+?) \(.*/, '\1') }
end

#versionsObject



168
169
170
171
172
# File 'lib/pod/command/lib/testing.rb', line 168

def versions
  sdks = `xcodebuild -version -sdk 2>/dev/null`.split("\n")
  sdks = sdks.select { |sdk| sdk[/iphonesimulator/] }
  sdks.map { |sdk| sdk.gsub(/.*\(iphonesimulator(.*)\)/, '\1') }
end