unobtainium 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a7dfaed7fd3b12c6c2506ec09194c34f9939ef16
4
+ data.tar.gz: 535afb416ce0449d2d4a96bfc5a57cbcd8a93224
5
+ SHA512:
6
+ metadata.gz: dec4e9b74f39c887ce315209cd340363eca9b02bc47e9637337b7195b1dabe467ee3a69e66f41fde71400afcfddfa1a453a83a1a9a757fb818f5a81ade292091
7
+ data.tar.gz: 8599bcf5b567faf0294cd6c1fbb820b06d64a61c413f4979427a3527ed39b97867d9cb4f891b63b55e7a2ea8cfa4aaa030b9803862a0961051b21a613bbe776e
data/.gitignore ADDED
@@ -0,0 +1,39 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+
18
+ ## Documentation cache and generated files:
19
+ /.yardoc/
20
+ /_yardoc/
21
+ /doc/
22
+ /rdoc/
23
+
24
+ ## Environment normalization:
25
+ /.bundle/
26
+ /vendor/bundle
27
+ /lib/bundler/man/
28
+
29
+ # for a library or gem, you might want to ignore these files since the code is
30
+ # intended to run in multiple environments; otherwise, check them in:
31
+ # Gemfile.lock
32
+ # .ruby-version
33
+ # .ruby-gemset
34
+
35
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
+ .rvmrc
37
+
38
+ # Editor files
39
+ .*.sw*
data/.rubocop.yml ADDED
@@ -0,0 +1,54 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.2
3
+
4
+ # Metrics
5
+
6
+ Metrics/LineLength:
7
+ Max: 83
8
+ Details: >-
9
+ Line length of 80 is ideal for readability and compatibility; we'll accept
10
+ an extra 3 for minor edge cases.
11
+
12
+ Metrics/MethodLength:
13
+ Max: 35
14
+
15
+ Metrics/BlockNesting:
16
+ Max: 5
17
+
18
+ Metrics/AbcSize:
19
+ Max: 50
20
+
21
+ Metrics/PerceivedComplexity:
22
+ Max: 15
23
+
24
+ Metrics/CyclomaticComplexity:
25
+ Max: 15
26
+
27
+ # Style
28
+
29
+ Style/StringLiterals:
30
+ Enabled: false
31
+
32
+ Style/ConditionalAssignment:
33
+ Enabled: false
34
+
35
+ Style/EmptyLinesAroundModuleBody:
36
+ Enabled: false
37
+
38
+ Style/AndOr:
39
+ Enabled: false
40
+
41
+ Style/Not:
42
+ Enabled: false
43
+
44
+ Style/NegatedIf:
45
+ Enabled: false
46
+
47
+ Style/RedundantReturn:
48
+ Enabled: false
49
+
50
+ Style/IfUnlessModifier:
51
+ Enabled: false
52
+
53
+ Style/TrailingCommaInLiteral:
54
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in unobtainium.gemspec
4
+ gemspec
5
+
6
+ gem 'selenium-webdriver'
7
+ gem 'appium_lib'
data/Gemfile.lock ADDED
@@ -0,0 +1,55 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ unobtainium (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ appium_lib (8.0.2)
10
+ awesome_print (~> 1.6)
11
+ json (~> 1.8)
12
+ nokogiri (~> 1.6.6)
13
+ selenium-webdriver (~> 2.49)
14
+ tomlrb (~> 1.1)
15
+ ast (2.2.0)
16
+ awesome_print (1.6.1)
17
+ childprocess (0.5.9)
18
+ ffi (~> 1.0, >= 1.0.11)
19
+ ffi (1.9.10)
20
+ json (1.8.3)
21
+ mini_portile2 (2.0.0)
22
+ nokogiri (1.6.7.2)
23
+ mini_portile2 (~> 2.0.0.rc2)
24
+ parser (2.3.0.7)
25
+ ast (~> 2.2)
26
+ powerpack (0.1.1)
27
+ rainbow (2.1.0)
28
+ rubocop (0.39.0)
29
+ parser (>= 2.3.0.7, < 3.0)
30
+ powerpack (~> 0.1)
31
+ rainbow (>= 1.99.1, < 3.0)
32
+ ruby-progressbar (~> 1.7)
33
+ unicode-display_width (~> 1.0, >= 1.0.1)
34
+ ruby-progressbar (1.7.5)
35
+ rubyzip (1.2.0)
36
+ selenium-webdriver (2.53.0)
37
+ childprocess (~> 0.5)
38
+ rubyzip (~> 1.0)
39
+ websocket (~> 1.0)
40
+ tomlrb (1.2.0)
41
+ unicode-display_width (1.0.3)
42
+ websocket (1.2.2)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ appium_lib
49
+ bundler (~> 1.11)
50
+ rubocop (~> 0.39)
51
+ selenium-webdriver
52
+ unobtainium!
53
+
54
+ BUNDLED WITH
55
+ 1.11.2
data/LICENSE ADDED
@@ -0,0 +1,30 @@
1
+ Copyright (c) Jens Finkhaeuser (http://finkhaeuser.de/) and other unobtainum
2
+ contributors. All rights not covered below are reserved.
3
+
4
+ The MIT +no-false-attribs License (MITNFA)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to
8
+ deal in the Software without restriction, including without limitation the
9
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
+ sell copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ Distributions of all or part of the Software intended to be used by the
17
+ recipients as they would use the unmodified Software, containing modifications
18
+ that substantially alter, remove, or disable functionality of the Software,
19
+ outside of the documented configuration mechanisms provided by the Software,
20
+ shall be modified such that the Original Author's bug reporting email addresses
21
+ and urls are either replaced with the contact information of the parties
22
+ responsible for the changes, or removed entirely.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30
+ IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # unobtainium
2
+ *Obtain the unobtainable: test code covering multiple platforms*
3
+
4
+ Unobtainium wraps [Selenium](https://github.com/SeleniumHQ/selenium) and
5
+ [Appium](https://github.com/appium/ruby_lib) in a simple driver abstraction
6
+ so that test code can more easily cover:
7
+
8
+ - Desktop browsers
9
+ - Mobile browsers
10
+ - Mobile apps
11
+
12
+ Some additional useful functionality for the maintenance of test suites is
13
+ also added.
14
+
15
+ # Credits
16
+ This gem is inspired by [LapisLazuli](https://github.com/spriteCloud/lapis-lazuli),
17
+ but vastly less complex, and aims to stay so.
@@ -0,0 +1,12 @@
1
+ # coding: utf-8
2
+ #
3
+ # unobtainium
4
+ # https://github.com/jfinkhaeuser/unobtainium
5
+ #
6
+ # Copyright (c) 2016 Jens Finkhaeuser and other unobtainium contributors.
7
+ # All rights reserved.
8
+ #
9
+
10
+ require 'unobtainium/version'
11
+
12
+ require 'unobtainium/driver'
@@ -0,0 +1,135 @@
1
+
2
+ # coding: utf-8
3
+ #
4
+ # unobtainium
5
+ # https://github.com/jfinkhaeuser/unobtainium
6
+ #
7
+ # Copyright (c) 2016 Jens Finkhaeuser and other unobtainium contributors.
8
+ # All rights reserved.
9
+ #
10
+ module Unobtainium
11
+
12
+ ##
13
+ # Creating a Driver instance creates either an Appium or Selenium driver
14
+ # depending on the arguments, and delegates all else to the underlying
15
+ # implementation.
16
+ #
17
+ # It's possible to add more drivers, but Appium and Selenium are the main
18
+ # targets.
19
+ class Driver
20
+ ############################################################################
21
+ # Class methods
22
+ class << self
23
+ ##
24
+ # Create a driver instance with the given arguments
25
+ def create(*args)
26
+ Driver.new(*args)
27
+ end
28
+ end # class << self
29
+
30
+ ############################################################################
31
+ # Public methods
32
+ attr_reader :label, :options, :impl
33
+
34
+ ##
35
+ # Initializer
36
+ def initialize(*args)
37
+ # Sanitize options
38
+ @label, @options = sanitize_options(*args)
39
+
40
+ # Load drivers
41
+ load_drivers
42
+
43
+ # Determine the driver class, if any
44
+ driver_klass = get_driver(@label)
45
+ if not driver_klass
46
+ raise LoadError, "No driver implementation matching #{@label} found, "\
47
+ "aborting!"
48
+ end
49
+
50
+ # Perform precondition checks of the driver class
51
+ driver_klass.ensure_preconditions(@label, @options)
52
+
53
+ # Great, instanciate!
54
+ @impl = driver_klass.create(@label, @options)
55
+ end
56
+
57
+ private
58
+
59
+ # Class variables have their place, rubocop... still, err on the strict
60
+ # side and just skip this check here.
61
+ # rubocop:disable Style/ClassVars
62
+ @@drivers = {}
63
+ # rubocop:enable Style/ClassVars
64
+
65
+ # Methods that drivers must implement
66
+ DRIVER_METHODS = [
67
+ :matches?,
68
+ :ensure_preconditions,
69
+ :create
70
+ ].freeze
71
+
72
+ ##
73
+ # FIXME
74
+ def sanitize_options(*args)
75
+ load_drivers
76
+ require 'pp'
77
+ pp args
78
+ end
79
+
80
+ ##
81
+ # Load drivers.
82
+ def load_drivers
83
+ # TODO: add load path for external drivers, or let them be specified via
84
+ # the driver environment/config variables.
85
+ pattern = File.join(File.dirname(__FILE__), 'drivers', '*.rb')
86
+ Dir.glob(pattern).each do |fpath|
87
+ # Determine class name from file name
88
+ fname = File.basename(fpath, '.rb')
89
+ fname = fname.split('_').map(&:capitalize).join
90
+
91
+ begin
92
+ require fpath
93
+ klassname = 'Unobtainium::Drivers::' + fname
94
+ klass = Object.const_get(klassname)
95
+ klass_methods = klass.methods - klass.instance_methods - Object.methods
96
+
97
+ if DRIVER_METHODS - klass_methods != []
98
+ raise LoadError, "Driver #{klassname} is not implementing all of "\
99
+ "#{DRIVER_METHODS}, aborting!"
100
+ end
101
+
102
+ if @@drivers.include?(klass) and @@drivers[klass] != fpath
103
+ raise LoadError, "Driver #{klassname} is duplicated in file "\
104
+ "'#{fpath}'; previous definition is here: "\
105
+ "'#{@@drivers[klass]}'"
106
+ end
107
+ @@drivers[klass] = fpath
108
+
109
+ rescue LoadError => err
110
+ raise LoadError, "#{err.message}: unknown problem loading driver, "\
111
+ "aborting!"
112
+ rescue NameError => err
113
+ raise LoadError, "#{err.message}: unknown problem loading driver, "\
114
+ "aborting!"
115
+ end
116
+ end
117
+ end
118
+
119
+ ##
120
+ # Out of the loaded drivers, returns the one matching the label (if any)
121
+ def get_driver(label)
122
+ # Of all the loaded classes, choose the first (unsorted) to match the
123
+ # requested driver label
124
+ impl = nil
125
+ @@drivers.keys.each do |klass|
126
+ if klass.matches?(label)
127
+ impl = klass
128
+ break
129
+ end
130
+ end
131
+
132
+ return impl
133
+ end
134
+ end # class Driver
135
+ end # module Unobtainium
@@ -0,0 +1,132 @@
1
+ # coding: utf-8
2
+ #
3
+ # unobtainium
4
+ # https://github.com/jfinkhaeuser/unobtainium
5
+ #
6
+ # Copyright (c) 2016 Jens Finkhaeuser and other unobtainium contributors.
7
+ # All rights reserved.
8
+ #
9
+ module Unobtainium
10
+ module Drivers
11
+
12
+ ##
13
+ # Driver implementation wrapping the appium_lib gem.
14
+ class Appium
15
+ # Recognized labels for matching the driver
16
+ LABELS = {
17
+ appium: [],
18
+ ios: [:iphone, :ipad],
19
+ android: [],
20
+ }.freeze
21
+
22
+ # Browser matches for some platforms
23
+ # TODO: add many more matches
24
+ BROWSER_MATCHES = {
25
+ android: {
26
+ chrome: {
27
+ appPackage: 'com.android.chrome',
28
+ appActivity: 'com.google.android.apps.chrome.Main',
29
+ },
30
+ },
31
+ }.freeze
32
+
33
+ class << self
34
+ ##
35
+ # Return true if the given label matches this driver implementation,
36
+ # false otherwise.
37
+ def matches?(label)
38
+ return nil != normalize_label(label)
39
+ end
40
+
41
+ ##
42
+ # Ensure that the driver's preconditions are fulfilled.
43
+ def ensure_preconditions(_, _)
44
+ require 'appium_lib'
45
+ rescue LoadError => err
46
+ raise LoadError, "#{err.message}: you need to add "\
47
+ "'appium_lib' to your Gemfile to use this driver!",
48
+ err.backtrace
49
+ end
50
+
51
+ ##
52
+ # Create and return a driver instance
53
+ def create(label, options)
54
+ # The label specifies the platform, if no other platform is given.
55
+ normalized = normalize_label(label)
56
+
57
+ if not options.is_a? Hash
58
+ options = {}
59
+ end
60
+ if not options['caps'].is_a? Hash
61
+ options['caps'] = {}
62
+ end
63
+
64
+ if options['caps']['platformName'].nil?
65
+ options['caps']['platformName'] = normalized.to_s
66
+ end
67
+
68
+ # If no app is given, but a browser is requested, we can supplement
69
+ # some information
70
+ options = supplement_browser(options)
71
+
72
+ # Create the driver
73
+ driver = ::Appium::Driver.new(options).start_driver
74
+ return driver
75
+ end
76
+
77
+ private
78
+
79
+ ##
80
+ # For a recognized label alias, returns a normalized label.
81
+ def normalize_label(label)
82
+ LABELS.each do |normalized, aliases|
83
+ if label == normalized or aliases.include?(label)
84
+ return normalized
85
+ end
86
+ end
87
+ return nil
88
+ end
89
+
90
+ ##
91
+ # If the driver options include a request for a browser, we can
92
+ # supplement some missing specs in the options.
93
+ def supplement_browser(options)
94
+ # Can't do anything without a browser request.
95
+ if options['browser'].nil?
96
+ return options
97
+ end
98
+ browser = options['browser'].downcase.to_sym
99
+
100
+ # Platform
101
+ platform = options['caps']['platformName'].to_s.downcase.to_sym
102
+
103
+ # If we have supplement data matching the platform and browser, great!
104
+ data = BROWSER_MATCHES[platform][browser]
105
+ if data.nil?
106
+ return options
107
+ end
108
+
109
+ # We do have to check that we're not overwriting any of the keys.
110
+ data.keys.each do |key|
111
+ key_s = key.to_s
112
+ if not options['caps'].key?(key) and not options['caps'].key?(key_s)
113
+ next
114
+ end
115
+ raise ArgumentError, "You specified the browser option as, "\
116
+ "'#{options['browser']}', but you also have the key "\
117
+ "'#{key}' set in your requested capabilities. Use one or the"\
118
+ "other."
119
+ end
120
+
121
+ # Merge, but also stringify symbol keys
122
+ data.each do |key, value|
123
+ options['caps'][key.to_s] = value
124
+ end
125
+
126
+ options
127
+ end
128
+ end # class << self
129
+ end # class Selenium
130
+
131
+ end # module Drivers
132
+ end # module Unobtainium
@@ -0,0 +1,65 @@
1
+ # coding: utf-8
2
+ #
3
+ # unobtainium
4
+ # https://github.com/jfinkhaeuser/unobtainium
5
+ #
6
+ # Copyright (c) 2016 Jens Finkhaeuser and other unobtainium contributors.
7
+ # All rights reserved.
8
+ #
9
+ module Unobtainium
10
+ module Drivers
11
+
12
+ ##
13
+ # Driver implementation wrapping the selenium-webdriver gem.
14
+ class Selenium
15
+ # Recognized labels for matching the driver
16
+ LABELS = {
17
+ firefox: [:ff,],
18
+ internet_explorer: [:internetexplorer, :explorer, :ie,],
19
+ safari: [],
20
+ chrome: [],
21
+ chromium: [],
22
+ }.freeze
23
+
24
+ class << self
25
+ ##
26
+ # Return true if the given label matches this driver implementation,
27
+ # false otherwise.
28
+ def matches?(label)
29
+ return nil != normalize_label(label)
30
+ end
31
+
32
+ ##
33
+ # Ensure that the driver's preconditions are fulfilled.
34
+ def ensure_preconditions(_, _)
35
+ require 'selenium-webdriver'
36
+ rescue LoadError => err
37
+ raise LoadError, "#{err.message}: you need to add "\
38
+ "'selenium-webdriver' to your Gemfile to use this driver!",
39
+ err.backtrace
40
+ end
41
+
42
+ ##
43
+ # Create and return a driver instance
44
+ def create(label, _)
45
+ driver = ::Selenium::WebDriver.for(normalize_label(label))
46
+ return driver
47
+ end
48
+
49
+ private
50
+
51
+ ##
52
+ # For a recognized label alias, returns a normalized label.
53
+ def normalize_label(label)
54
+ LABELS.each do |normalized, aliases|
55
+ if label == normalized or aliases.include?(label)
56
+ return normalized
57
+ end
58
+ end
59
+ return nil
60
+ end
61
+ end # class << self
62
+ end # class Selenium
63
+
64
+ end # module Drivers
65
+ end # module Unobtainium
@@ -0,0 +1,11 @@
1
+ # coding: utf-8
2
+ #
3
+ # unobtainium
4
+ # https://github.com/jfinkhaeuser/unobtainium
5
+ #
6
+ # Copyright (c) 2016 Jens Finkhaeuser and other unobtainium contributors.
7
+ # All rights reserved.
8
+ #
9
+ module Unobtainium
10
+ VERSION = "0.0.1".freeze
11
+ end
@@ -0,0 +1,47 @@
1
+ # coding: utf-8
2
+ #
3
+ # unobtainium
4
+ # https://github.com/jfinkhaeuser/unobtainium
5
+ #
6
+ # Copyright (c) 2016 Jens Finkhaeuser and other unobtainium contributors.
7
+ # All rights reserved.
8
+ #
9
+
10
+ lib = File.expand_path('../lib', __FILE__)
11
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
12
+ require 'unobtainium/version'
13
+
14
+ # rubocop:disable Style/UnneededPercentQ, Style/ExtraSpacing
15
+ # rubocop:disable Style/SpaceAroundOperators
16
+ Gem::Specification.new do |spec|
17
+ spec.name = "unobtainium"
18
+ spec.version = Unobtainium::VERSION
19
+ spec.authors = ["Jens Finkhaeuser"]
20
+ spec.email = ["jens@finkhaeuser.de"]
21
+ spec.description = %q(
22
+ Unobtainium wraps Selenium and Appium in a simple driver abstraction so that
23
+ test code can more easily cover:
24
+
25
+ - Desktop browsers
26
+ - Mobile browsers
27
+ - Mobile apps
28
+
29
+ Some additional useful functionality for the maintenance of test suites is
30
+ also added.
31
+ )
32
+ spec.summary = %q(
33
+ Obtain the unobtainable: test code covering multiple platforms
34
+ )
35
+ spec.homepage = "https://github.com/jfinkhaeuser/unobtainium"
36
+ spec.license = "MITNFA"
37
+
38
+ spec.files = `git ls-files -z`.split("\x0")
39
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
40
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
41
+ spec.require_paths = ["lib"]
42
+
43
+ spec.add_development_dependency "bundler", "~> 1.11"
44
+ spec.add_development_dependency "rubocop", "~> 0.39"
45
+ end
46
+ # rubocop:enable Style/SpaceAroundOperators
47
+ # rubocop:enable Style/UnneededPercentQ, Style/ExtraSpacing
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unobtainium
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jens Finkhaeuser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.39'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.39'
41
+ description: "\n Unobtainium wraps Selenium and Appium in a simple driver abstraction
42
+ so that\n test code can more easily cover:\n\n - Desktop browsers\n -
43
+ Mobile browsers\n - Mobile apps\n\n Some additional useful functionality
44
+ for the maintenance of test suites is\n also added.\n "
45
+ email:
46
+ - jens@finkhaeuser.de
47
+ executables: []
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - ".gitignore"
52
+ - ".rubocop.yml"
53
+ - Gemfile
54
+ - Gemfile.lock
55
+ - LICENSE
56
+ - README.md
57
+ - lib/unobtainium.rb
58
+ - lib/unobtainium/driver.rb
59
+ - lib/unobtainium/drivers/appium.rb
60
+ - lib/unobtainium/drivers/selenium.rb
61
+ - lib/unobtainium/version.rb
62
+ - unobtainium.gemspec
63
+ homepage: https://github.com/jfinkhaeuser/unobtainium
64
+ licenses:
65
+ - MITNFA
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 2.4.5.1
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: 'Obtain the unobtainable: test code covering multiple platforms'
87
+ test_files: []
88
+ has_rdoc: