learn-test 2.5.4 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.circleci/config.yml +59 -0
- data/.gitignore +0 -1
- data/Gemfile +4 -1
- data/Gemfile.lock +83 -0
- data/LICENSE.txt +1 -1
- data/README.md +2 -3
- data/bin/learn-test +8 -0
- data/learn-test.gemspec +4 -3
- data/lib/learn_test.rb +2 -1
- data/lib/learn_test/client.rb +1 -1
- data/lib/learn_test/js_strategy.rb +7 -3
- data/lib/learn_test/repo_parser.rb +2 -3
- data/lib/learn_test/runner.rb +2 -2
- data/lib/learn_test/strategies/pytest.rb +85 -0
- data/lib/learn_test/strategies/{python_unittest → pytest}/requirements_checker.rb +21 -19
- data/lib/learn_test/strategies/rspec.rb +8 -0
- data/lib/learn_test/username_parser.rb +1 -1
- data/lib/learn_test/version.rb +1 -1
- data/spec/features/rspec_unit_spec.rb +26 -1
- data/spec/fixtures/.netrc +3 -0
- data/spec/fixtures/rspec-unit-spec/spec/dog_spec.rb +8 -0
- data/spec/learn_test/username_parser_spec.rb +61 -0
- data/spec/lib/learn_test/strategies/mocha_spec.rb +20 -17
- metadata +30 -12
- data/lib/learn_test/strategies/python_unittest.rb +0 -72
- data/lib/learn_test/strategies/python_unittest/nose_installer.rb +0 -35
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a98ee1823d7eaa0784005b131da8261b48f009c5479536157d2061ef1e9ec29f
|
|
4
|
+
data.tar.gz: 21dfb4ce2145c6c662f0ef0c0c686ad80a325920cd506c8629e730dcbdbd6430
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f11dbf50918100c382e61b8457ca1edda76685766045afbc546bac3d08eada57c08b3e6a5272793ff0c4a5b6ac9f1dc2cf8b03558a0a7197c3271fe17b6c0d71
|
|
7
|
+
data.tar.gz: 4341c6a7b0fd636b3302ec4dd5c49f0b9a50ee3b261542a2304167596dd3d7c2a301f1289e747a3d2e5e912eb08edea7ac99ef34cf6dad80a5a5c6a582074566
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
version: 2.1
|
|
2
|
+
|
|
3
|
+
jobs:
|
|
4
|
+
build:
|
|
5
|
+
docker:
|
|
6
|
+
- image: circleci/ruby:2.5.8
|
|
7
|
+
|
|
8
|
+
working_directory: ~/repo
|
|
9
|
+
|
|
10
|
+
steps:
|
|
11
|
+
- checkout
|
|
12
|
+
|
|
13
|
+
- restore_cache:
|
|
14
|
+
keys:
|
|
15
|
+
- gems-v3-{{ checksum "Gemfile.lock" }}
|
|
16
|
+
- gems-v3-
|
|
17
|
+
|
|
18
|
+
- run:
|
|
19
|
+
name: Force Bundler Version
|
|
20
|
+
command: |
|
|
21
|
+
sudo gem update --system
|
|
22
|
+
echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV
|
|
23
|
+
source $BASH_ENV
|
|
24
|
+
|
|
25
|
+
- run:
|
|
26
|
+
name: Install Dependencies
|
|
27
|
+
command: |
|
|
28
|
+
bundle config --local set vendor/bundle
|
|
29
|
+
bundle install
|
|
30
|
+
|
|
31
|
+
- save_cache:
|
|
32
|
+
key: gems-v3-{{ checksum "Gemfile.lock" }}
|
|
33
|
+
paths:
|
|
34
|
+
- vendor/bundle
|
|
35
|
+
|
|
36
|
+
- run:
|
|
37
|
+
name: Create ~/.netrc
|
|
38
|
+
command: |
|
|
39
|
+
cp spec/fixtures/.netrc ~/
|
|
40
|
+
chmod 0600 ~/.netrc
|
|
41
|
+
|
|
42
|
+
- run:
|
|
43
|
+
name: Run tests
|
|
44
|
+
command: |
|
|
45
|
+
mkdir /tmp/test-results
|
|
46
|
+
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
|
|
47
|
+
|
|
48
|
+
bundle exec rspec --format progress \
|
|
49
|
+
--format RspecJunitFormatter \
|
|
50
|
+
--out /tmp/test-results/rspec.xml \
|
|
51
|
+
--format progress \
|
|
52
|
+
$TEST_FILES
|
|
53
|
+
|
|
54
|
+
- store_test_results:
|
|
55
|
+
path: /tmp/test-results
|
|
56
|
+
|
|
57
|
+
- store_artifacts:
|
|
58
|
+
path: /tmp/test-results
|
|
59
|
+
destination: test-results
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
learn-test (2.6.1)
|
|
5
|
+
colorize (~> 0.8.1)
|
|
6
|
+
crack (~> 0.4.3)
|
|
7
|
+
faraday (~> 0.9)
|
|
8
|
+
git (~> 1.2)
|
|
9
|
+
jasmine (~> 2.6.0, >= 2.6.0)
|
|
10
|
+
jasmine-core (< 2.99.1)
|
|
11
|
+
netrc (~> 0.11.0)
|
|
12
|
+
oj (~> 2.9)
|
|
13
|
+
rainbow (= 1.99.2)
|
|
14
|
+
rspec (~> 3.0)
|
|
15
|
+
selenium-webdriver (~> 2.52.0, >= 2.52.0)
|
|
16
|
+
webrick (~> 1.3.1, >= 1.3.1)
|
|
17
|
+
|
|
18
|
+
GEM
|
|
19
|
+
remote: https://rubygems.org/
|
|
20
|
+
specs:
|
|
21
|
+
childprocess (0.9.0)
|
|
22
|
+
ffi (~> 1.0, >= 1.0.11)
|
|
23
|
+
colorize (0.8.1)
|
|
24
|
+
crack (0.4.3)
|
|
25
|
+
safe_yaml (~> 1.0.0)
|
|
26
|
+
diff-lcs (1.4.4)
|
|
27
|
+
faraday (0.17.3)
|
|
28
|
+
multipart-post (>= 1.2, < 3)
|
|
29
|
+
ffi (1.13.1)
|
|
30
|
+
git (1.7.0)
|
|
31
|
+
rchardet (~> 1.8)
|
|
32
|
+
jasmine (2.6.0)
|
|
33
|
+
jasmine-core (>= 2.6.0, < 3.0.0)
|
|
34
|
+
phantomjs
|
|
35
|
+
rack (>= 1.2.1)
|
|
36
|
+
rake
|
|
37
|
+
jasmine-core (2.99.0)
|
|
38
|
+
multi_json (1.15.0)
|
|
39
|
+
multipart-post (2.1.1)
|
|
40
|
+
netrc (0.11.0)
|
|
41
|
+
oj (2.18.5)
|
|
42
|
+
phantomjs (2.1.1.0)
|
|
43
|
+
rack (2.2.3)
|
|
44
|
+
rainbow (1.99.2)
|
|
45
|
+
rake (13.0.1)
|
|
46
|
+
rchardet (1.8.0)
|
|
47
|
+
rspec (3.9.0)
|
|
48
|
+
rspec-core (~> 3.9.0)
|
|
49
|
+
rspec-expectations (~> 3.9.0)
|
|
50
|
+
rspec-mocks (~> 3.9.0)
|
|
51
|
+
rspec-core (3.9.2)
|
|
52
|
+
rspec-support (~> 3.9.3)
|
|
53
|
+
rspec-expectations (3.9.2)
|
|
54
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
55
|
+
rspec-support (~> 3.9.0)
|
|
56
|
+
rspec-mocks (3.9.1)
|
|
57
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
58
|
+
rspec-support (~> 3.9.0)
|
|
59
|
+
rspec-support (3.9.3)
|
|
60
|
+
rspec_junit_formatter (0.4.1)
|
|
61
|
+
rspec-core (>= 2, < 4, != 2.12.0)
|
|
62
|
+
rubyzip (1.3.0)
|
|
63
|
+
safe_yaml (1.0.5)
|
|
64
|
+
selenium-webdriver (2.52.0)
|
|
65
|
+
childprocess (~> 0.5)
|
|
66
|
+
multi_json (~> 1.0)
|
|
67
|
+
rubyzip (~> 1.0)
|
|
68
|
+
websocket (~> 1.0)
|
|
69
|
+
webrick (1.3.1)
|
|
70
|
+
websocket (1.2.8)
|
|
71
|
+
|
|
72
|
+
PLATFORMS
|
|
73
|
+
ruby
|
|
74
|
+
|
|
75
|
+
DEPENDENCIES
|
|
76
|
+
bundler (~> 2.1.4)
|
|
77
|
+
learn-test!
|
|
78
|
+
rake (~> 13.0.1)
|
|
79
|
+
rspec (~> 3.8)
|
|
80
|
+
rspec_junit_formatter (~> 0.4.1)
|
|
81
|
+
|
|
82
|
+
BUNDLED WITH
|
|
83
|
+
2.1.4
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# learn-test
|
|
2
2
|
|
|
3
|
-
Runs RSpec, Jasmine, and Python
|
|
3
|
+
Runs RSpec, Jasmine, and Python Pytest test suites and uploads the results to Learn.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -22,7 +22,7 @@ And then execute:
|
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
24
24
|
|
|
25
|
-
From within a directory with an RSpec, Jasmine, Karma, Mocha, or Python
|
|
25
|
+
From within a directory with an RSpec, Jasmine, Karma, Mocha, or Python Pytest test suite, run:
|
|
26
26
|
|
|
27
27
|
```
|
|
28
28
|
$ learn-test
|
|
@@ -35,4 +35,3 @@ $ learn-test
|
|
|
35
35
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
36
36
|
4. Push to the branch (`git push origin my-new-feature`)
|
|
37
37
|
5. Create a new Pull Request
|
|
38
|
-
|
data/bin/learn-test
CHANGED
|
@@ -8,6 +8,10 @@ options = {}
|
|
|
8
8
|
OptionParser.new do |opts|
|
|
9
9
|
opts.banner = "Usage: learn [options]"
|
|
10
10
|
|
|
11
|
+
opts.on("--sync", "Report test results synchronously") do |s|
|
|
12
|
+
options[:sync] = s
|
|
13
|
+
end
|
|
14
|
+
|
|
11
15
|
opts.on("-d", "--debug", "Output errors during results synchronization") do |d|
|
|
12
16
|
options[:debug] = d
|
|
13
17
|
end
|
|
@@ -53,6 +57,10 @@ OptionParser.new do |opts|
|
|
|
53
57
|
options[:fail_fast] = f
|
|
54
58
|
end
|
|
55
59
|
|
|
60
|
+
opts.on("-e", "--example STRING", "Run examples whose full nested names include STRING (may be used more than once)") do |s|
|
|
61
|
+
(options[:example] ||= []) << s
|
|
62
|
+
end
|
|
63
|
+
|
|
56
64
|
if ARGV.any? { |arg| arg == "init" }
|
|
57
65
|
options[:init] = true
|
|
58
66
|
end
|
data/learn-test.gemspec
CHANGED
|
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
|
8
8
|
spec.version = LearnTest::VERSION
|
|
9
9
|
spec.authors = ["Flatiron School"]
|
|
10
10
|
spec.email = ["learn@flatironschool.com"]
|
|
11
|
-
spec.summary = %q{Runs RSpec, Jasmine, Karma, Mocha, and Python
|
|
11
|
+
spec.summary = %q{Runs RSpec, Jasmine, Karma, Mocha, and Python Pytest Test builds and pushes JSON output to Learn.}
|
|
12
12
|
spec.homepage = "https://github.com/learn-co/learn-test"
|
|
13
13
|
spec.license = "MIT"
|
|
14
14
|
|
|
@@ -18,8 +18,9 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.require_paths = ["lib", "bin"]
|
|
19
19
|
spec.required_ruby_version = '>= 2.3.0'
|
|
20
20
|
|
|
21
|
-
spec.add_development_dependency "bundler", "~> 1.
|
|
22
|
-
spec.add_development_dependency "rake", "~>
|
|
21
|
+
spec.add_development_dependency "bundler", "~> 2.1.4"
|
|
22
|
+
spec.add_development_dependency "rake", "~> 13.0.1"
|
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.8"
|
|
23
24
|
spec.add_runtime_dependency "rspec", "~> 3.0"
|
|
24
25
|
spec.add_runtime_dependency "netrc", "~> 0.11.0"
|
|
25
26
|
spec.add_runtime_dependency "git", "~> 1.2"
|
data/lib/learn_test.rb
CHANGED
|
@@ -17,7 +17,6 @@ require_relative 'learn_test/dependency'
|
|
|
17
17
|
require_relative 'learn_test/strategy'
|
|
18
18
|
require_relative 'learn_test/js_strategy'
|
|
19
19
|
require_relative 'learn_test/strategies/jasmine'
|
|
20
|
-
require_relative 'learn_test/strategies/python_unittest'
|
|
21
20
|
require_relative 'learn_test/strategies/rspec'
|
|
22
21
|
require_relative 'learn_test/strategies/karma'
|
|
23
22
|
require_relative 'learn_test/strategies/protractor'
|
|
@@ -25,6 +24,7 @@ require_relative 'learn_test/strategies/java_junit'
|
|
|
25
24
|
require_relative 'learn_test/strategies/csharp_nunit'
|
|
26
25
|
require_relative 'learn_test/strategies/mocha'
|
|
27
26
|
require_relative 'learn_test/strategies/green_onion'
|
|
27
|
+
require_relative 'learn_test/strategies/pytest'
|
|
28
28
|
|
|
29
29
|
module LearnTest
|
|
30
30
|
module Dependencies
|
|
@@ -39,5 +39,6 @@ module LearnTest
|
|
|
39
39
|
autoload :SeleniumServer, 'learn_test/dependencies/selenium_server'
|
|
40
40
|
autoload :Firefox, 'learn_test/dependencies/firefox'
|
|
41
41
|
autoload :GreenOnion, 'learn_test/dependencies/green_onion'
|
|
42
|
+
autoload :Pytest, 'learn_test/dependencies/pytest'
|
|
42
43
|
end
|
|
43
44
|
end
|
data/lib/learn_test/client.rb
CHANGED
|
@@ -3,7 +3,7 @@ require 'json'
|
|
|
3
3
|
|
|
4
4
|
module LearnTest
|
|
5
5
|
class Client
|
|
6
|
-
SERVICE_URL = 'http://ironbroker-v2.flatironschool.com'.freeze
|
|
6
|
+
SERVICE_URL = ENV.fetch('IRONBROKER_URL', 'http://ironbroker-v2.flatironschool.com').freeze
|
|
7
7
|
|
|
8
8
|
def initialize(service_url = SERVICE_URL)
|
|
9
9
|
@conn = Faraday.new(url: service_url) do |faraday|
|
|
@@ -8,11 +8,15 @@ module LearnTest
|
|
|
8
8
|
[:dependencies, :devDependencies].any? { |key| js_package[key] && js_package[key][dep] }
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def modules_missing?(module_names)
|
|
12
|
+
module_names.any? { |name| !File.exist?("node_modules/#{name}") }
|
|
13
|
+
end
|
|
14
|
+
|
|
11
15
|
def missing_dependencies?
|
|
12
16
|
return true if !File.exist?("node_modules")
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
(
|
|
17
|
+
[:dependencies, :devDependencies, :peerDependencies].any? do |dep_group|
|
|
18
|
+
modules = js_package[dep_group] || {}
|
|
19
|
+
modules_missing?(modules.keys)
|
|
16
20
|
end
|
|
17
21
|
end
|
|
18
22
|
|
|
@@ -6,14 +6,14 @@ module LearnTest
|
|
|
6
6
|
begin
|
|
7
7
|
repo = Git.open(FileUtils.pwd)
|
|
8
8
|
rescue
|
|
9
|
-
puts "You don't appear to be in a Learn lesson's directory. Please cd to an appropriate directory and try again."
|
|
9
|
+
puts "You don't appear to be in a Learn lesson's directory. Please enter 'learn open' or cd to an appropriate directory and try again."
|
|
10
10
|
die
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
if url = repo.remote.url
|
|
14
14
|
url.match(/(?:https?:\/\/|git@).*\/(.+?)(?:\.git)?$/)[1]
|
|
15
15
|
else
|
|
16
|
-
puts "You don't appear to be in a Learn lesson's directory. Please cd to an appropriate directory and try again."
|
|
16
|
+
puts "You don't appear to be in a Learn lesson's directory. Please enter 'learn open' or cd to an appropriate directory and try again."
|
|
17
17
|
die
|
|
18
18
|
end
|
|
19
19
|
end
|
|
@@ -23,4 +23,3 @@ module LearnTest
|
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
|
-
|
data/lib/learn_test/runner.rb
CHANGED
|
@@ -14,7 +14,7 @@ module LearnTest
|
|
|
14
14
|
strategy.check_dependencies
|
|
15
15
|
strategy.configure
|
|
16
16
|
strategy.run
|
|
17
|
-
if options[:debug]
|
|
17
|
+
if options[:debug] || options[:sync]
|
|
18
18
|
report_and_clean
|
|
19
19
|
else
|
|
20
20
|
Process.detach(Process.fork do
|
|
@@ -57,7 +57,7 @@ module LearnTest
|
|
|
57
57
|
LearnTest::Strategies::Protractor,
|
|
58
58
|
LearnTest::Strategies::JavaJunit,
|
|
59
59
|
LearnTest::Strategies::Mocha,
|
|
60
|
-
LearnTest::Strategies::
|
|
60
|
+
LearnTest::Strategies::Pytest,
|
|
61
61
|
]
|
|
62
62
|
end
|
|
63
63
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require 'crack'
|
|
2
|
+
require_relative 'pytest/requirements_checker'
|
|
3
|
+
|
|
4
|
+
module LearnTest
|
|
5
|
+
module Strategies
|
|
6
|
+
class Pytest < LearnTest::Strategy
|
|
7
|
+
|
|
8
|
+
def service_endpoint
|
|
9
|
+
'/e/flatiron_pytest'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def detect
|
|
13
|
+
test_files.count > 0
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def check_dependencies
|
|
17
|
+
LearnTest::Pytest::RequirementsChecker.check_installation
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def run
|
|
21
|
+
system("python -m pytest #{options[:argv].join(' ')} --junitxml='./.results.xml'")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def output
|
|
25
|
+
@output ||= Crack::XML.parse(File.read('.results.xml'))["testsuite"]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_files
|
|
29
|
+
# pytest will run all files of the form test_*.py or *_test.py
|
|
30
|
+
@test_files ||= Dir.glob("**/test_*.py") + Dir.glob("**/*_test.py")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def results
|
|
34
|
+
failed_count = output["failures"].to_i + output["errors"].to_i
|
|
35
|
+
skipped_count = output["skips"].to_i
|
|
36
|
+
passed_count = output["tests"].to_i - failed_count - skipped_count
|
|
37
|
+
{
|
|
38
|
+
username: username,
|
|
39
|
+
github_user_id: user_id,
|
|
40
|
+
learn_oauth_token: learn_oauth_token,
|
|
41
|
+
repo_name: runner.repo,
|
|
42
|
+
build: {
|
|
43
|
+
test_suite: [{
|
|
44
|
+
framework: 'pytest',
|
|
45
|
+
formatted_output: output.to_json,
|
|
46
|
+
duration: output["time"]
|
|
47
|
+
}]
|
|
48
|
+
},
|
|
49
|
+
examples: output["tests"].to_i,
|
|
50
|
+
passing_count: passed_count,
|
|
51
|
+
pending_count: skipped_count,
|
|
52
|
+
failure_count: failed_count,
|
|
53
|
+
failure_descriptions: concat_failure_descriptions
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def cleanup
|
|
58
|
+
FileUtils.rm('.results.xml')
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def calculate_duration
|
|
64
|
+
output[:results].map do |example|
|
|
65
|
+
example[:time]
|
|
66
|
+
end.inject(:+)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def concat_failure_descriptions
|
|
70
|
+
# if there is a single test the `testcase` xml parse turns out a hash
|
|
71
|
+
# instead of an array with a single hash. this will make sure single
|
|
72
|
+
# tests have the same output structure (Array) as multiple tests
|
|
73
|
+
output["testcase"] = [output["testcase"]].flatten
|
|
74
|
+
|
|
75
|
+
output["testcase"].reduce([]) do |errors, example|
|
|
76
|
+
if example.has_key?("failure")
|
|
77
|
+
errors << example.map{|k, v| "#{k}: #{v}"}
|
|
78
|
+
end
|
|
79
|
+
errors
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -1,35 +1,28 @@
|
|
|
1
1
|
require 'open3'
|
|
2
2
|
|
|
3
3
|
module LearnTest
|
|
4
|
-
module
|
|
4
|
+
module Pytest
|
|
5
5
|
class RequirementsChecker
|
|
6
6
|
def self.check_installation
|
|
7
|
-
new.check_installation
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def check_installation
|
|
11
7
|
PythonChecker.check
|
|
12
8
|
PipChecker.check
|
|
9
|
+
PytestChecker.check
|
|
13
10
|
end
|
|
14
11
|
end
|
|
15
12
|
|
|
16
13
|
class PythonChecker
|
|
17
14
|
def self.check
|
|
18
|
-
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def check
|
|
22
|
-
if !python_installed? || !correct_python_version?
|
|
15
|
+
if !self.python_installed? || !self.correct_python_version?
|
|
23
16
|
puts "Please install python 2.7.x or 3.x.x"
|
|
24
17
|
exit
|
|
25
18
|
end
|
|
26
19
|
end
|
|
27
20
|
|
|
28
|
-
def python_installed?
|
|
21
|
+
def self.python_installed?
|
|
29
22
|
!`which python`.empty?
|
|
30
23
|
end
|
|
31
24
|
|
|
32
|
-
def correct_python_version?
|
|
25
|
+
def self.correct_python_version?
|
|
33
26
|
output = Open3.popen2e('python', '--version')
|
|
34
27
|
version = output[1].read.strip
|
|
35
28
|
!!version.match(/ 2.7.*| 3.*/)
|
|
@@ -38,20 +31,29 @@ module LearnTest
|
|
|
38
31
|
|
|
39
32
|
class PipChecker
|
|
40
33
|
def self.check
|
|
41
|
-
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def check
|
|
45
|
-
if !pip_installed?
|
|
34
|
+
if !self.pip_installed?
|
|
46
35
|
puts "Please ensure pip is installed"
|
|
47
36
|
exit
|
|
48
37
|
end
|
|
49
38
|
end
|
|
50
39
|
|
|
51
|
-
def pip_installed?
|
|
40
|
+
def self.pip_installed?
|
|
52
41
|
!`which pip`.empty?
|
|
53
42
|
end
|
|
54
43
|
end
|
|
44
|
+
|
|
45
|
+
class PytestChecker
|
|
46
|
+
def self.check
|
|
47
|
+
if !self.pytest_installed?
|
|
48
|
+
puts "Please ensure pytest is installed"
|
|
49
|
+
exit
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.pytest_installed?
|
|
54
|
+
!`which pytest`.empty?
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
55
58
|
end
|
|
56
59
|
end
|
|
57
|
-
|
|
@@ -25,6 +25,10 @@ module LearnTest
|
|
|
25
25
|
argv << '--fail-fast'
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
if example_option_present?
|
|
29
|
+
argv << options[:example].map{|e| "--example #{e}"}.join(" ")
|
|
30
|
+
end
|
|
31
|
+
|
|
28
32
|
# Don't pass the test/local flag from learn binary to rspec runner.
|
|
29
33
|
argv.delete("--test")
|
|
30
34
|
argv.delete("-t")
|
|
@@ -83,6 +87,10 @@ module LearnTest
|
|
|
83
87
|
options[:fail_fast]
|
|
84
88
|
end
|
|
85
89
|
|
|
90
|
+
def example_option_present?
|
|
91
|
+
options[:example]
|
|
92
|
+
end
|
|
93
|
+
|
|
86
94
|
def dot_rspec
|
|
87
95
|
@dot_rspec ||= File.readlines('.rspec').map(&:strip) if File.exist?('.rspec')
|
|
88
96
|
end
|
|
@@ -7,7 +7,7 @@ module LearnTest
|
|
|
7
7
|
|
|
8
8
|
if !LearnTest::LearnOauthTokenParser.get_learn_oauth_token && (!username || user_id == 'none')
|
|
9
9
|
print "Enter your github username: "
|
|
10
|
-
username = gets.strip
|
|
10
|
+
username = $stdin.gets.strip
|
|
11
11
|
user_id = LearnTest::GithubInteractor.get_user_id_for(username)
|
|
12
12
|
parser.write(username, user_id)
|
|
13
13
|
end
|
data/lib/learn_test/version.rb
CHANGED
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
describe "Running a RSpec Unit Test" do
|
|
2
|
+
before(:all) do
|
|
3
|
+
# While it doesn't cause these tests to fail, nasty messages occur (and more)
|
|
4
|
+
# when either a ~/.netrc entry or file itself doesn't exist. This aims to correct that,
|
|
5
|
+
# and will only ever be called once.
|
|
6
|
+
|
|
7
|
+
LearnTest::UsernameParser.get_username
|
|
8
|
+
end
|
|
9
|
+
|
|
2
10
|
context 'a basic rspec unit test' do
|
|
3
11
|
it 'runs the spec with 0 failures' do
|
|
4
12
|
output = `cd ./spec/fixtures/rspec-unit-spec && ./../../../bin/learn-test --local --test`
|
|
5
13
|
|
|
6
|
-
expect(output).to include('
|
|
14
|
+
expect(output).to include('3 examples, 0 failures')
|
|
7
15
|
expect(output).to_not include('1 failures')
|
|
8
16
|
end
|
|
9
17
|
end
|
|
18
|
+
|
|
19
|
+
context 'with the --example flag' do
|
|
20
|
+
it 'runs only the appropriate tests' do
|
|
21
|
+
output = `cd ./spec/fixtures/rspec-unit-spec && ./../../../bin/learn-test --local --test --example multiple`
|
|
22
|
+
|
|
23
|
+
expect(output).to include('1 example, 0 failures')
|
|
24
|
+
expect(output).to_not include('2 examples')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'accepts multiple examples' do
|
|
28
|
+
output = `cd ./spec/fixtures/rspec-unit-spec && ./../../../bin/learn-test --local --test --example multiple --example accepts`
|
|
29
|
+
|
|
30
|
+
expect(output).to include('2 examples, 0 failures')
|
|
31
|
+
expect(output).to_not include('3 examples')
|
|
32
|
+
expect(output).to_not include('1 example')
|
|
33
|
+
end
|
|
34
|
+
end
|
|
10
35
|
end
|
|
@@ -4,4 +4,12 @@ describe Dog do
|
|
|
4
4
|
it 'runs the spec spec correctly' do
|
|
5
5
|
expect(subject).to be_an_instance_of(Dog)
|
|
6
6
|
end
|
|
7
|
+
|
|
8
|
+
it 'has multiple specs' do
|
|
9
|
+
expect(subject).not_to be_an_instance_of(String)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'accepts more than one example' do
|
|
13
|
+
expect(subject).not_to be_an_instance_of(String)
|
|
14
|
+
end
|
|
7
15
|
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
describe LearnTest::UsernameParser do
|
|
2
|
+
subject { LearnTest::UsernameParser }
|
|
3
|
+
|
|
4
|
+
let(:dbl) { instance_double(LearnTest::NetrcInteractor) }
|
|
5
|
+
|
|
6
|
+
let!(:username) { 'learn-co' }
|
|
7
|
+
let!(:user_id) { '12345' }
|
|
8
|
+
let!(:token) { 'abc123' }
|
|
9
|
+
|
|
10
|
+
context 'user details are stored in ~/.netrc' do
|
|
11
|
+
context 'username/password' do
|
|
12
|
+
it 'should return a username' do
|
|
13
|
+
expect(LearnTest::LearnOauthTokenParser).to receive(:get_learn_oauth_token).and_return(token)
|
|
14
|
+
|
|
15
|
+
expect(LearnTest::NetrcInteractor).to receive(:new).and_return(dbl)
|
|
16
|
+
expect(dbl).to receive(:username).and_return(username)
|
|
17
|
+
expect(dbl).to receive(:user_id).and_return(user_id)
|
|
18
|
+
|
|
19
|
+
expect(dbl).to_not receive(:write)
|
|
20
|
+
|
|
21
|
+
expect(subject.get_username).to eq(username)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context 'oauth token' do
|
|
26
|
+
it 'should return a username' do
|
|
27
|
+
expect(LearnTest::LearnOauthTokenParser).to receive(:get_learn_oauth_token).and_return(token)
|
|
28
|
+
|
|
29
|
+
expect(LearnTest::NetrcInteractor).to receive(:new).and_return(dbl)
|
|
30
|
+
expect(dbl).to receive(:username).and_return(nil)
|
|
31
|
+
expect(dbl).to receive(:user_id).and_return(nil)
|
|
32
|
+
|
|
33
|
+
expect(dbl).to_not receive(:write)
|
|
34
|
+
|
|
35
|
+
expect(subject.get_username).to eq(nil)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'user details are not stored in ~/.netrc' do
|
|
41
|
+
it 'should ask for and store a username' do
|
|
42
|
+
@original_stdout = $stdout
|
|
43
|
+
$stdout = File.open(File::NULL, 'w')
|
|
44
|
+
|
|
45
|
+
expect(LearnTest::LearnOauthTokenParser).to receive(:get_learn_oauth_token).and_return(nil)
|
|
46
|
+
|
|
47
|
+
expect(LearnTest::NetrcInteractor).to receive(:new).and_return(dbl)
|
|
48
|
+
expect(dbl).to receive(:username).and_return(nil)
|
|
49
|
+
expect(dbl).to receive(:user_id).and_return(nil)
|
|
50
|
+
|
|
51
|
+
expect($stdin).to receive(:gets).and_return(username)
|
|
52
|
+
expect(LearnTest::GithubInteractor).to receive(:get_user_id_for).with(username).and_return(user_id)
|
|
53
|
+
expect(dbl).to receive(:write).with(username, user_id)
|
|
54
|
+
|
|
55
|
+
expect(subject.get_username).to eq(username)
|
|
56
|
+
|
|
57
|
+
$stdout = @original_stdout
|
|
58
|
+
@original_stdout = nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -16,44 +16,47 @@ describe LearnTest::Strategies::Mocha do
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
end
|
|
19
|
+
|
|
19
20
|
let(:runner) { double("Runner", options: {}) }
|
|
20
21
|
let(:strategy) { LearnTest::Strategies::Mocha.new(runner) }
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
context "node_modules/ does not exist" do
|
|
24
|
+
it "returns true" do
|
|
25
|
+
allow(File).to receive(:exist?).with("node_modules").and_return(false)
|
|
26
|
+
expect(strategy.missing_dependencies?).to eq(true)
|
|
27
|
+
end
|
|
26
28
|
end
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
|
|
31
|
+
context "node_modules/ exists" do
|
|
29
32
|
before(:each) do
|
|
30
|
-
allow(File).to receive(:
|
|
33
|
+
allow(File).to receive(:exist?).and_return(true)
|
|
34
|
+
allow(strategy).to receive(:js_package).and_return(package)
|
|
31
35
|
end
|
|
32
36
|
|
|
33
37
|
it "returns true if missing a dependency" do
|
|
34
|
-
|
|
35
|
-
expect(
|
|
36
|
-
expect(strategy.missing_dependencies?(package)).to eq(true)
|
|
38
|
+
allow(File).to receive(:exist?).with("node_modules/dep2").and_return(false)
|
|
39
|
+
expect(strategy.missing_dependencies?).to eq(true)
|
|
37
40
|
end
|
|
38
41
|
|
|
39
42
|
it "returns true if missing a devDependency" do
|
|
40
|
-
|
|
41
|
-
expect(
|
|
42
|
-
expect(strategy.missing_dependencies?(package)).to eq(true)
|
|
43
|
+
allow(File).to receive(:exist?).with("node_modules/devDep2").and_return(false)
|
|
44
|
+
expect(strategy.missing_dependencies?).to eq(true)
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
it "returns true if missing a peerDependency" do
|
|
46
|
-
|
|
47
|
-
expect(
|
|
48
|
-
expect(strategy.missing_dependencies?(package)).to eq(true)
|
|
48
|
+
allow(File).to receive(:exist?).with("node_modules/peerDep2").and_return(false)
|
|
49
|
+
expect(strategy.missing_dependencies?).to eq(true)
|
|
49
50
|
end
|
|
50
51
|
|
|
51
52
|
it "returns false if missing no dependencies" do
|
|
52
|
-
|
|
53
|
+
allow(File).to receive(:exist?).and_return(true)
|
|
54
|
+
expect(strategy.missing_dependencies?).to eq(false)
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
it "returns false if there are no dependencies" do
|
|
56
|
-
|
|
58
|
+
allow(strategy).to receive(:js_package).and_return({})
|
|
59
|
+
expect(strategy.missing_dependencies?).to eq(false)
|
|
57
60
|
end
|
|
58
61
|
end
|
|
59
62
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: learn-test
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Flatiron School
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-07-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -16,28 +16,42 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
19
|
+
version: 2.1.4
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
26
|
+
version: 2.1.4
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
33
|
+
version: 13.0.1
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
40
|
+
version: 13.0.1
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.8'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.8'
|
|
41
55
|
- !ruby/object:Gem::Dependency
|
|
42
56
|
name: rspec
|
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -232,9 +246,11 @@ executables:
|
|
|
232
246
|
extensions: []
|
|
233
247
|
extra_rdoc_files: []
|
|
234
248
|
files:
|
|
249
|
+
- ".circleci/config.yml"
|
|
235
250
|
- ".gitignore"
|
|
236
251
|
- ".rspec"
|
|
237
252
|
- Gemfile
|
|
253
|
+
- Gemfile.lock
|
|
238
254
|
- LICENSE.txt
|
|
239
255
|
- README.md
|
|
240
256
|
- Rakefile
|
|
@@ -289,9 +305,8 @@ files:
|
|
|
289
305
|
- lib/learn_test/strategies/karma/karma.conf.js
|
|
290
306
|
- lib/learn_test/strategies/mocha.rb
|
|
291
307
|
- lib/learn_test/strategies/protractor.rb
|
|
292
|
-
- lib/learn_test/strategies/
|
|
293
|
-
- lib/learn_test/strategies/
|
|
294
|
-
- lib/learn_test/strategies/python_unittest/requirements_checker.rb
|
|
308
|
+
- lib/learn_test/strategies/pytest.rb
|
|
309
|
+
- lib/learn_test/strategies/pytest/requirements_checker.rb
|
|
295
310
|
- lib/learn_test/strategies/rspec.rb
|
|
296
311
|
- lib/learn_test/strategy.rb
|
|
297
312
|
- lib/learn_test/user_id_parser.rb
|
|
@@ -304,6 +319,7 @@ files:
|
|
|
304
319
|
- node_modules/karma-json-reporter/package.json
|
|
305
320
|
- spec/features/jasmine_jquery_fixtures_spec.rb
|
|
306
321
|
- spec/features/rspec_unit_spec.rb
|
|
322
|
+
- spec/fixtures/.netrc
|
|
307
323
|
- spec/fixtures/jasmine-jquery-fixtures/index.html
|
|
308
324
|
- spec/fixtures/jasmine-jquery-fixtures/requires.yml
|
|
309
325
|
- spec/fixtures/jasmine-jquery-fixtures/spec/jasmine-jquery-fixtures-spec.js
|
|
@@ -312,6 +328,7 @@ files:
|
|
|
312
328
|
- spec/fixtures/rspec-unit-spec/spec/dog_spec.rb
|
|
313
329
|
- spec/fixtures/rspec-unit-spec/spec/spec_helper.rb
|
|
314
330
|
- spec/learn_test/reporter_spec.rb
|
|
331
|
+
- spec/learn_test/username_parser_spec.rb
|
|
315
332
|
- spec/lib/learn_test/strategies/mocha_spec.rb
|
|
316
333
|
- spec/repo_parser_spec.rb
|
|
317
334
|
- spec/spec_helper.rb
|
|
@@ -335,15 +352,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
335
352
|
- !ruby/object:Gem::Version
|
|
336
353
|
version: '0'
|
|
337
354
|
requirements: []
|
|
338
|
-
|
|
339
|
-
rubygems_version: 2.6.14
|
|
355
|
+
rubygems_version: 3.1.2
|
|
340
356
|
signing_key:
|
|
341
357
|
specification_version: 4
|
|
342
|
-
summary: Runs RSpec, Jasmine, Karma, Mocha, and Python
|
|
358
|
+
summary: Runs RSpec, Jasmine, Karma, Mocha, and Python Pytest Test builds and pushes
|
|
343
359
|
JSON output to Learn.
|
|
344
360
|
test_files:
|
|
345
361
|
- spec/features/jasmine_jquery_fixtures_spec.rb
|
|
346
362
|
- spec/features/rspec_unit_spec.rb
|
|
363
|
+
- spec/fixtures/.netrc
|
|
347
364
|
- spec/fixtures/jasmine-jquery-fixtures/index.html
|
|
348
365
|
- spec/fixtures/jasmine-jquery-fixtures/requires.yml
|
|
349
366
|
- spec/fixtures/jasmine-jquery-fixtures/spec/jasmine-jquery-fixtures-spec.js
|
|
@@ -352,6 +369,7 @@ test_files:
|
|
|
352
369
|
- spec/fixtures/rspec-unit-spec/spec/dog_spec.rb
|
|
353
370
|
- spec/fixtures/rspec-unit-spec/spec/spec_helper.rb
|
|
354
371
|
- spec/learn_test/reporter_spec.rb
|
|
372
|
+
- spec/learn_test/username_parser_spec.rb
|
|
355
373
|
- spec/lib/learn_test/strategies/mocha_spec.rb
|
|
356
374
|
- spec/repo_parser_spec.rb
|
|
357
375
|
- spec/spec_helper.rb
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
require_relative 'python_unittest/requirements_checker'
|
|
2
|
-
require_relative 'python_unittest/nose_installer'
|
|
3
|
-
|
|
4
|
-
module LearnTest
|
|
5
|
-
module Strategies
|
|
6
|
-
class PythonUnittest < LearnTest::Strategy
|
|
7
|
-
def service_endpoint
|
|
8
|
-
'/e/flatiron_unittest'
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def detect
|
|
12
|
-
test_files.any? {|f| f.match(/.*\.py$/) }
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def check_dependencies
|
|
16
|
-
LearnTest::PythonUnittest::RequirementsChecker.check_installation
|
|
17
|
-
LearnTest::PythonUnittest::NoseInstaller.install
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def run
|
|
21
|
-
system("nosetests #{options[:argv].join(' ')} --verbose --with-json --json-file='./.results.json'")
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def output
|
|
25
|
-
@output ||= Oj.load(File.read('.results.json'), symbol_keys: true)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def test_files
|
|
29
|
-
@test_files ||= Dir.glob("**/*_test.py")
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def results
|
|
33
|
-
{
|
|
34
|
-
username: username,
|
|
35
|
-
github_user_id: user_id,
|
|
36
|
-
learn_oauth_token: learn_oauth_token,
|
|
37
|
-
repo_name: runner.repo,
|
|
38
|
-
build: {
|
|
39
|
-
test_suite: [{
|
|
40
|
-
framework: 'unittest',
|
|
41
|
-
formatted_output: output,
|
|
42
|
-
duration: calculate_duration
|
|
43
|
-
}]
|
|
44
|
-
},
|
|
45
|
-
examples: output[:stats][:total],
|
|
46
|
-
passing_count: output[:stats][:passes],
|
|
47
|
-
pending_count: output[:stats][:skipped],
|
|
48
|
-
failure_count: output[:stats][:errors],
|
|
49
|
-
failure_descriptions: concat_failure_descriptions
|
|
50
|
-
}
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def cleanup
|
|
54
|
-
FileUtils.rm('.results.json')
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
private
|
|
58
|
-
|
|
59
|
-
def calculate_duration
|
|
60
|
-
output[:results].map do |example|
|
|
61
|
-
example[:time]
|
|
62
|
-
end.inject(:+)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def concat_failure_descriptions
|
|
66
|
-
output[:results].select do |example|
|
|
67
|
-
example[:type] == 'failure'
|
|
68
|
-
end.map { |ex| ex[:tb] }.join(';')
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
module LearnTest
|
|
2
|
-
module PythonUnittest
|
|
3
|
-
class NoseInstaller
|
|
4
|
-
def self.install
|
|
5
|
-
new.install
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def install
|
|
9
|
-
install_nose
|
|
10
|
-
install_nose_json
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def install_nose
|
|
14
|
-
if !nose_installed?
|
|
15
|
-
`easy_install nose`
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def nose_installed?
|
|
20
|
-
!`which nosetests`.empty?
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def install_nose_json
|
|
24
|
-
if !nose_json_installed?
|
|
25
|
-
`pip install nose-json`
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def nose_json_installed?
|
|
30
|
-
!`pip show nose-json`.empty?
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|