Skip to content

Commit 08dc711

Browse files
kylefdnkoutso
authored andcommitted
Introduce test_specification DSL
1 parent a4e2164 commit 08dc711

File tree

9 files changed

+149
-10
lines changed

9 files changed

+149
-10
lines changed

CHANGELOG.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
##### Enhancements
66

7-
* None.
7+
* Introduce `test_specification` DSL
8+
[Dimitris Koutsogiorgas](https://github.com/dnkoutso)
9+
[Kyle Fuller](https://github.com/kylef)
10+
[#369](https://github.com/CocoaPods/Core/pull/369)
811

912
##### Bug Fixes
1013

lib/cocoapods-core/specification.rb

+30-7
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,18 @@ class Specification
3434
# @param [String] name
3535
# the name of the specification.
3636
#
37-
def initialize(parent = nil, name = nil)
37+
# @param [Bool] test_specification
38+
# Whether the specification is a test specification
39+
#
40+
def initialize(parent = nil, name = nil, test_specification = false)
3841
@attributes_hash = {}
3942
@subspecs = []
4043
@consumers = {}
4144
@parent = parent
4245
@hash_value = nil
46+
@test_specification = test_specification
4347
attributes_hash['name'] = name
48+
attributes_hash['test_type'] = :unit if test_specification
4449

4550
yield self if block_given?
4651
end
@@ -203,7 +208,26 @@ def subspec?
203208

204209
# @!group Dependencies & Subspecs
205210

206-
# @return [Array<Specifications>] the recursive list of all the subspecs of
211+
# @return [Bool] if the specification is a test specification
212+
#
213+
def test_specification?
214+
@test_specification
215+
end
216+
217+
# @return [Symbol] the test type supported if this is a test specification
218+
#
219+
def test_type
220+
attributes_hash['test_type']
221+
end
222+
223+
# @return [Array<Specification>] the list of all the test subspecs of
224+
# a specification.
225+
#
226+
def test_specs
227+
subspecs.select(&:test_specification?)
228+
end
229+
230+
# @return [Array<Specification>] the recursive list of all the subspecs of
207231
# a specification.
208232
#
209233
def recursive_subspecs
@@ -241,7 +265,7 @@ def subspec_by_name(relative_name, raise_if_missing = true)
241265
else
242266
remainder = relative_name[base_name.size + 1..-1]
243267
subspec_name = remainder.split('/').shift
244-
subspec = subspecs.find { |s| s.base_name == subspec_name }
268+
subspec = subspecs.find { |s| s.base_name == subspec_name && !s.test_specification? }
245269
unless subspec
246270
if raise_if_missing
247271
raise Informative, 'Unable to find a specification named ' \
@@ -274,7 +298,7 @@ def default_subspecs
274298
#
275299
def subspec_dependencies(platform = nil)
276300
specs = if default_subspecs.empty?
277-
subspecs.compact
301+
subspecs.compact.reject(&:test_specification?)
278302
else
279303
default_subspecs.map do |subspec_name|
280304
root.subspec_by_name("#{name}/#{subspec_name}")
@@ -288,9 +312,8 @@ def subspec_dependencies(platform = nil)
288312

289313
# Returns the dependencies on other Pods or subspecs of other Pods.
290314
#
291-
# @param [Bool] all_platforms
292-
# whether the dependencies should be returned for all platforms
293-
# instead of the active one.
315+
# @param [Platform] platform
316+
# return only dependencies supported on the given platform.
294317
#
295318
# @note External dependencies are inherited by subspecs
296319
#

lib/cocoapods-core/specification/consumer.rb

+5
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ def user_target_xcconfig
182182
#
183183
spec_attr_accessor :preserve_paths
184184

185+
# @return [Symbol] the directory from where to preserve the headers
186+
# namespacing.
187+
#
188+
spec_attr_accessor :test_type
189+
185190
#-----------------------------------------------------------------------#
186191

187192
# @return [Array<Dependency>] the dependencies on other Pods.

lib/cocoapods-core/specification/dsl.rb

+42
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,48 @@ def subspec(name, &block)
13241324
subspec
13251325
end
13261326

1327+
# The names of the test types currently supported.
1328+
#
1329+
TEST_TYPES = [:unit].freeze
1330+
1331+
# The test type this specification supports. This only applies to test specifications.
1332+
#
1333+
# ---
1334+
#
1335+
# @example
1336+
#
1337+
# test_spec.test_type = :unit
1338+
#
1339+
# @param [Symbol] type
1340+
# The test type to use.
1341+
attribute :test_type,
1342+
:container => Array,
1343+
:types => [Symbol],
1344+
:keys => TEST_TYPES,
1345+
:multi_platform => false
1346+
1347+
# Represents a test specification for the library. Here you can place all
1348+
# your tests for your podspec along with the test dependencies.
1349+
#
1350+
# ---
1351+
#
1352+
# @example
1353+
#
1354+
# Pod::Spec.new do |spec|
1355+
# spec.name = 'NSAttributedString+CCLFormat'
1356+
#
1357+
# spec.test_spec do |test_spec|
1358+
# test_spec.source_files = 'NSAttributedString+CCLFormatTests.m'
1359+
# test_spec.dependency 'Expecta'
1360+
# end
1361+
# end
1362+
#
1363+
def test_spec(name = 'Tests', &block)
1364+
subspec = Specification.new(self, name, true, &block)
1365+
@subspecs << subspec
1366+
subspec
1367+
end
1368+
13271369
#------------------#
13281370

13291371
# @!method default_subspecs=(subspec_array)

lib/cocoapods-core/specification/linter.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def run_root_validation_hooks
128128
run_validation_hooks(attributes, spec)
129129
end
130130

131-
# Run validations for multi-platform attributes activating .
131+
# Run validations for multi-platform attributes activating.
132132
#
133133
# @return [void]
134134
#

lib/cocoapods-core/specification/linter/analyzer.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ def analyze
4242
def check_attributes
4343
attributes_keys = Pod::Specification::DSL.attributes.keys.map(&:to_s)
4444
platform_keys = Specification::DSL::PLATFORMS.map(&:to_s)
45-
valid_keys = attributes_keys + platform_keys
45+
test_keys = Specification::DSL::TEST_TYPES.map(&:to_s)
46+
valid_keys = attributes_keys + platform_keys + test_keys
4647
attributes_hash = consumer.spec.attributes_hash
4748
keys = attributes_hash.keys
4849
Specification::DSL::PLATFORMS.each do |platform|

spec/specification/dsl_spec.rb

+21
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,27 @@ module Pod
368368

369369
#-----------------------------------------------------------------------------#
370370

371+
describe 'Test specs' do
372+
before do
373+
@spec = Spec.new do |spec|
374+
spec.name = 'Spec'
375+
spec.test_spec do |test_spec|
376+
test_spec.test_type = :unit
377+
end
378+
end
379+
end
380+
381+
it 'allows you to specify a test spec' do
382+
test_spec = @spec.subspecs.first
383+
test_spec.class.should == Specification
384+
test_spec.name.should == 'Spec/Tests'
385+
test_spec.test_specification?.should == true
386+
test_spec.test_type.should == :unit
387+
end
388+
end
389+
390+
#-----------------------------------------------------------------------------#
391+
371392
describe 'Multi-Platform' do
372393
before do
373394
@spec = Spec.new do |s|

spec/specification/linter/analyzer_spec.rb

+9
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ module Pod
9090
results.first.attribute_name.should.include?('keys')
9191
end
9292

93+
it 'fails a spec with unknown sub-keys for test' do
94+
@spec.test_type = :unknown
95+
results = @analyzer.analyze
96+
results.count.should.be.equal(1)
97+
expected = 'Unrecognized `unknown` key'
98+
results.first.message.should.include?(expected)
99+
results.first.attribute_name.should.include?('keys')
100+
end
101+
93102
it 'validates a spec with valid minor sub-keys' do
94103
@spec.source = { :git => 'example.com', :branch => 'master' }
95104
results = @analyzer.analyze

spec/specification_spec.rb

+35
Original file line numberDiff line numberDiff line change
@@ -217,23 +217,30 @@ module Pod
217217
s.name = 'Pod'
218218
s.subspec 'Subspec' do |_sp|
219219
end
220+
s.test_spec do |_tsp|
221+
end
220222
end
221223
@subspec = @spec.subspecs.first
224+
@test_subspec = @spec.test_specs.first
222225
end
223226

224227
it 'returns the root spec' do
225228
@spec.root.should == @spec
226229
@subspec.root.should == @spec
230+
@test_subspec.root.should == @spec
227231
end
228232

229233
it 'returns whether it is a root spec' do
230234
@spec.root?.should.be.true
231235
@subspec.root?.should.be.false
236+
@test_subspec.root?.should.be.false
232237
end
233238

234239
it 'returns whether it is a subspec' do
235240
@spec.subspec?.should.be.false
236241
@subspec.subspec?.should.be.true
242+
@test_subspec.subspec?.should.be.true
243+
@test_subspec.test_specification?.should.be.true
237244
end
238245
end
239246

@@ -273,6 +280,17 @@ module Pod
273280
@spec.subspec_by_name('Pod/Subspec/Subsubspec').should == @subsubspec
274281
end
275282

283+
it "doesn't return the test subspec given the Tests name" do
284+
@spec = Spec.new do |s|
285+
s.name = 'Pod'
286+
s.version = '1.0'
287+
s.dependency 'AFNetworking'
288+
s.osx.dependency 'MagicalRecord'
289+
s.test_spec {}
290+
end
291+
@spec.subspec_by_name('Pod/Tests', false).should. nil?
292+
end
293+
276294
it 'returns a subspec given the relative name' do
277295
@subspec.subspec_by_name('Subspec/Subsubspec').should == @subsubspec
278296
end
@@ -327,12 +345,29 @@ module Pod
327345
]
328346
end
329347

348+
it 'excludes the test subspec from the subspec dependencies' do
349+
@spec.test_spec {}
350+
@spec.subspec_dependencies.sort.should == [
351+
Dependency.new('Pod/Subspec', '1.0'),
352+
Dependency.new('Pod/SubspecOSX', '1.0'),
353+
Dependency.new('Pod/SubspeciOS', '1.0')]
354+
end
355+
330356
it 'returns all the dependencies' do
331357
@spec.dependencies.sort.should == [
332358
Dependency.new('AFNetworking'),
333359
Dependency.new('MagicalRecord')]
334360
end
335361

362+
it 'returns the test spec dependencies' do
363+
test_spec = @spec.test_spec { |s| s.dependency 'OCMock' }
364+
test_spec.dependencies.sort.should == [
365+
Dependency.new('AFNetworking'),
366+
Dependency.new('MagicalRecord'),
367+
Dependency.new('OCMock'),
368+
]
369+
end
370+
336371
it 'returns the dependencies given the platform' do
337372
@spec.dependencies(:ios).sort.should == [Dependency.new('AFNetworking')]
338373
end

0 commit comments

Comments
 (0)