learn-test 1.1.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 +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +23 -0
- data/README.md +38 -0
- data/Rakefile +2 -0
- data/bin/learn-test +78 -0
- data/learn-test.gemspec +30 -0
- data/lib/learn_test.rb +26 -0
- data/lib/learn_test/file_finder.rb +12 -0
- data/lib/learn_test/github_interactor.rb +23 -0
- data/lib/learn_test/jasmine/boot.js +184 -0
- data/lib/learn_test/jasmine/console.js +161 -0
- data/lib/learn_test/jasmine/formatters/jasmine2-junit.js +199 -0
- data/lib/learn_test/jasmine/helpers/ConsoleHelper.js +12 -0
- data/lib/learn_test/jasmine/helpers/ConsoleHelperNoColor.js +12 -0
- data/lib/learn_test/jasmine/initializer.rb +27 -0
- data/lib/learn_test/jasmine/jasmine-html.js +360 -0
- data/lib/learn_test/jasmine/jasmine-jquery.js +813 -0
- data/lib/learn_test/jasmine/jasmine.css +56 -0
- data/lib/learn_test/jasmine/jasmine.js +2403 -0
- data/lib/learn_test/jasmine/jasmine_favicon.png +0 -0
- data/lib/learn_test/jasmine/jquery-1.8.0.min.js +2 -0
- data/lib/learn_test/jasmine/jquery-ui-1.8.23.custom.min.js +125 -0
- data/lib/learn_test/jasmine/phantom_checker.rb +55 -0
- data/lib/learn_test/jasmine/runner.rb +129 -0
- data/lib/learn_test/jasmine/runners/SpecRunner.html +35 -0
- data/lib/learn_test/jasmine/runners/run-jasmine.js +228 -0
- data/lib/learn_test/jasmine/templates/SpecRunnerTemplate.html.erb +35 -0
- data/lib/learn_test/jasmine/templates/SpecRunnerTemplateNoColor.html.erb +35 -0
- data/lib/learn_test/jasmine/templates/requires.yml.example +7 -0
- data/lib/learn_test/jasmine/vendor/require.js +2077 -0
- data/lib/learn_test/netrc_interactor.rb +18 -0
- data/lib/learn_test/python_unittest/nose_installer.rb +35 -0
- data/lib/learn_test/python_unittest/requirements_checker.rb +57 -0
- data/lib/learn_test/python_unittest/runner.rb +89 -0
- data/lib/learn_test/repo_parser.rb +22 -0
- data/lib/learn_test/rspec/runner.rb +113 -0
- data/lib/learn_test/spec_type_parser.rb +26 -0
- data/lib/learn_test/user_id_parser.rb +9 -0
- data/lib/learn_test/username_parser.rb +19 -0
- data/lib/learn_test/version.rb +3 -0
- data/spec/features/jasmine_jquery_fixtures_spec.rb +10 -0
- data/spec/features/rspec_unit_spec.rb +10 -0
- data/spec/fixtures/jasmine-jquery-fixtures/index.html +10 -0
- data/spec/fixtures/jasmine-jquery-fixtures/requires.yml +4 -0
- data/spec/fixtures/jasmine-jquery-fixtures/spec/jasmine-jquery-fixtures-spec.js +11 -0
- data/spec/fixtures/rspec-unit-spec/.rspec +2 -0
- data/spec/fixtures/rspec-unit-spec/lib/dog.rb +2 -0
- data/spec/fixtures/rspec-unit-spec/spec/dog_spec.rb +7 -0
- data/spec/fixtures/rspec-unit-spec/spec/spec_helper.rb +93 -0
- data/spec/repo_parser_spec.rb +25 -0
- data/spec/spec_helper.rb +10 -0
- metadata +237 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'netrc'
|
2
|
+
|
3
|
+
module LearnTest
|
4
|
+
class NetrcInteractor
|
5
|
+
attr_reader :username, :user_id, :netrc
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@netrc = Netrc.read
|
9
|
+
@username, @user_id = netrc["flatiron-push"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def write(username, user_id)
|
13
|
+
netrc["flatiron-push"] = username, user_id
|
14
|
+
netrc.save
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,35 @@
|
|
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
|
+
`pip 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
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module LearnTest
|
4
|
+
module PythonUnittest
|
5
|
+
class RequirementsChecker
|
6
|
+
def self.check_installation
|
7
|
+
new.check_installation
|
8
|
+
end
|
9
|
+
|
10
|
+
def check_installation
|
11
|
+
PythonChecker.check
|
12
|
+
PipChecker.check
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class PythonChecker
|
17
|
+
def self.check
|
18
|
+
new.check
|
19
|
+
end
|
20
|
+
|
21
|
+
def check
|
22
|
+
if !python_installed? || !correct_python_version?
|
23
|
+
puts "Please install python 2.7.x or 3.x.x"
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def python_installed?
|
29
|
+
!`which python`.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def correct_python_version?
|
33
|
+
output = Open3.popen3('python', '--version')
|
34
|
+
version = output[2].read.strip
|
35
|
+
!!version.match(/ 2.7.*| 3.*/)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class PipChecker
|
40
|
+
def self.check
|
41
|
+
new.check
|
42
|
+
end
|
43
|
+
|
44
|
+
def check
|
45
|
+
if !pip_installed?
|
46
|
+
puts "Please ensure pip is installed"
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def pip_installed?
|
52
|
+
!`which pip`.empty?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module LearnTest
|
2
|
+
module PythonUnittest
|
3
|
+
class Runner
|
4
|
+
attr_accessor :parsed_output, :json_output, :formatted_results
|
5
|
+
attr_reader :username, :user_id, :repo_name, :options, :connection
|
6
|
+
|
7
|
+
def initialize(username, user_id, repo_name, options)
|
8
|
+
@username = username
|
9
|
+
@user_id = user_id
|
10
|
+
@repo_name = repo_name
|
11
|
+
@options = options
|
12
|
+
@json_output = ""
|
13
|
+
@parsed_output = nil
|
14
|
+
@formatted_results = {}
|
15
|
+
@connection = Faraday.new(url: SERVICE_URL) do |faraday|
|
16
|
+
faraday.adapter Faraday.default_adapter
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
run_nose
|
22
|
+
if !options.include?('-h') && !options.include?('--help')
|
23
|
+
set_json_output
|
24
|
+
jsonify
|
25
|
+
format_results
|
26
|
+
push_results
|
27
|
+
cleanup
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_nose
|
32
|
+
system("nosetests #{options.join(' ')} --verbose --with-json --json-file='./.results.json'")
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_json_output
|
36
|
+
self.json_output = File.read('.results.json')
|
37
|
+
end
|
38
|
+
|
39
|
+
def jsonify
|
40
|
+
self.parsed_output = Oj.load(json_output, symbol_keys: true)
|
41
|
+
end
|
42
|
+
|
43
|
+
def format_results
|
44
|
+
self.formatted_results.merge!({
|
45
|
+
username: username,
|
46
|
+
github_user_id: user_id,
|
47
|
+
repo_name: repo_name,
|
48
|
+
build: {
|
49
|
+
test_suite: [{
|
50
|
+
framework: 'unittest',
|
51
|
+
formatted_output: parsed_output,
|
52
|
+
duration: calculate_duration
|
53
|
+
}]
|
54
|
+
},
|
55
|
+
examples: parsed_output[:stats][:total],
|
56
|
+
passing_count: parsed_output[:stats][:passes],
|
57
|
+
pending_count: parsed_output[:stats][:skipped],
|
58
|
+
failure_count: parsed_output[:stats][:errors],
|
59
|
+
failure_descriptions: concat_failure_descriptions
|
60
|
+
})
|
61
|
+
end
|
62
|
+
|
63
|
+
def calculate_duration
|
64
|
+
parsed_output[:results].map do |example|
|
65
|
+
example[:time]
|
66
|
+
end.inject(:+)
|
67
|
+
end
|
68
|
+
|
69
|
+
def concat_failure_descriptions
|
70
|
+
parsed_output[:results].select do |example|
|
71
|
+
example[:type] == 'failure'
|
72
|
+
end.map { |ex| ex[:tb] }.join(';')
|
73
|
+
end
|
74
|
+
|
75
|
+
def push_results
|
76
|
+
connection.post do |req|
|
77
|
+
req.url SERVICE_ENDPOINT
|
78
|
+
req.headers['Content-Type'] = 'application/json'
|
79
|
+
req.body = Oj.dump(formatted_results, mode: :compat)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def cleanup
|
84
|
+
FileUtils.rm('.results.json')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'git'
|
2
|
+
|
3
|
+
module LearnTest
|
4
|
+
class RepoParser
|
5
|
+
def self.get_repo
|
6
|
+
begin
|
7
|
+
repo = Git.open(FileUtils.pwd)
|
8
|
+
rescue
|
9
|
+
puts "Not a valid Git repository"
|
10
|
+
die
|
11
|
+
end
|
12
|
+
|
13
|
+
url = repo.remote.url
|
14
|
+
url.match(/(?:https:\/\/|git@).*\/(.+?)(?:\.git)?$/)[1]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.die
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module LearnTest
|
2
|
+
module RSpec
|
3
|
+
class Runner
|
4
|
+
attr_accessor :parsed_output, :json_output, :formatted_results
|
5
|
+
attr_reader :username, :user_id, :repo_name, :options, :connection
|
6
|
+
|
7
|
+
def initialize(username, user_id, repo_name, options)
|
8
|
+
@username = username
|
9
|
+
@user_id = user_id
|
10
|
+
@repo_name = repo_name
|
11
|
+
@options = options
|
12
|
+
@json_output = ""
|
13
|
+
@parsed_output = nil
|
14
|
+
@formatted_results = {}
|
15
|
+
@connection = Faraday.new(url: SERVICE_URL) do |faraday|
|
16
|
+
faraday.adapter Faraday.default_adapter
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
check_options
|
22
|
+
run_rspec
|
23
|
+
if !options.include?('-h') && !options.include?('--help')
|
24
|
+
set_json_output
|
25
|
+
jsonify
|
26
|
+
format_results
|
27
|
+
push_results
|
28
|
+
cleanup
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def check_options
|
33
|
+
options_has_format = options.include?('--format') || options.include?('-f')
|
34
|
+
if dot_rspec = read_dot_rspec
|
35
|
+
if options_has_format
|
36
|
+
if dot_rspec.any? {|dot_opt| dot_opt.match(/--format|-f/)}
|
37
|
+
options << dot_rspec.reject {|dot_opt| dot_opt.match(/--format|-f/)}
|
38
|
+
else
|
39
|
+
options << dot_rspec
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
if options_has_format
|
45
|
+
self.options.flatten!
|
46
|
+
else
|
47
|
+
options.unshift('--format documentation')
|
48
|
+
end
|
49
|
+
|
50
|
+
# Don't pass the test/local flag from learn binary to rspec runner.
|
51
|
+
options.delete("--test")
|
52
|
+
options.delete("-t")
|
53
|
+
options.delete("-l")
|
54
|
+
options.delete("--local")
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_dot_rspec
|
58
|
+
if File.exist?('.rspec')
|
59
|
+
File.readlines('.rspec').map(&:strip)
|
60
|
+
else
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def run_rspec
|
66
|
+
system("rspec #{options.join(' ')} --format j --out .results.json")
|
67
|
+
end
|
68
|
+
|
69
|
+
def set_json_output
|
70
|
+
self.json_output = File.read('.results.json')
|
71
|
+
end
|
72
|
+
|
73
|
+
def jsonify
|
74
|
+
self.parsed_output = Oj.load(json_output, symbol_keys: true)
|
75
|
+
end
|
76
|
+
|
77
|
+
def format_results
|
78
|
+
self.formatted_results.merge!({
|
79
|
+
username: username,
|
80
|
+
github_user_id: user_id,
|
81
|
+
repo_name: repo_name,
|
82
|
+
build: {
|
83
|
+
test_suite: [{
|
84
|
+
framework: 'rspec',
|
85
|
+
formatted_output: parsed_output,
|
86
|
+
duration: parsed_output[:summary][:duration]
|
87
|
+
}]
|
88
|
+
},
|
89
|
+
examples: parsed_output[:summary][:example_count],
|
90
|
+
passing_count: parsed_output[:summary][:example_count] - parsed_output[:summary][:failure_count] - parsed_output[:summary][:pending_count],
|
91
|
+
pending_count: parsed_output[:summary][:pending_count],
|
92
|
+
failure_count: parsed_output[:summary][:failure_count],
|
93
|
+
failure_descriptions: parsed_output[:examples].select do |example|
|
94
|
+
example[:status] == "failed"
|
95
|
+
end.map { |ex| ex[:full_description] }.join(";")
|
96
|
+
})
|
97
|
+
end
|
98
|
+
|
99
|
+
def push_results
|
100
|
+
connection.post do |req|
|
101
|
+
req.url SERVICE_ENDPOINT
|
102
|
+
req.headers['Content-Type'] = 'application/json'
|
103
|
+
req.body = Oj.dump(formatted_results, mode: :compat)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def cleanup
|
108
|
+
FileUtils.rm('.results.json')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module LearnTest
|
2
|
+
class SpecTypeParser
|
3
|
+
attr_reader :spec_type
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@spec_type = parse_spec_type
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def parse_spec_type
|
12
|
+
files = Dir.entries('.')
|
13
|
+
|
14
|
+
if files.include?('requires.yml')
|
15
|
+
'jasmine'
|
16
|
+
elsif files.any? {|f| f.match(/.*.py$/) }
|
17
|
+
'python_unittest'
|
18
|
+
elsif files.include?('spec')
|
19
|
+
spec_files = Dir.entries('./spec')
|
20
|
+
if spec_files.include?('spec_helper.rb') || spec_files.include?('rails_helper.rb')
|
21
|
+
'rspec'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module LearnTest
|
2
|
+
class UsernameParser
|
3
|
+
def self.get_username
|
4
|
+
parser = LearnTest::NetrcInteractor.new
|
5
|
+
username = parser.username
|
6
|
+
user_id = parser.user_id
|
7
|
+
|
8
|
+
if !username || user_id == 'none'
|
9
|
+
print "Enter your github username: "
|
10
|
+
username = gets.strip
|
11
|
+
user_id = LearnTest::GithubInteractor.get_user_id_for(username)
|
12
|
+
parser.write(username, user_id)
|
13
|
+
end
|
14
|
+
|
15
|
+
username
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
describe "Running a Jasmine jQuery Specs with Fixtures" do
|
2
|
+
context 'without a browser through PhantomJS' do
|
3
|
+
it 'runs the spec with 0 failures' do
|
4
|
+
output = `cd ./spec/fixtures/jasmine-jquery-fixtures && ./../../../bin/learn-test --local --test`
|
5
|
+
|
6
|
+
expect(output).to include('1 spec, 0 failures')
|
7
|
+
expect(output).to_not include('1 failures')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
describe "Running a RSpec Unit Test" do
|
2
|
+
context 'a basic rspec unit test' do
|
3
|
+
it 'runs the spec with 0 failures' do
|
4
|
+
output = `cd ./spec/fixtures/rspec-unit-spec && ./../../../bin/learn-test --local --test`
|
5
|
+
|
6
|
+
expect(output).to include('1 example, 0 failures')
|
7
|
+
expect(output).to_not include('1 failures')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
'use-strict';
|
2
|
+
|
3
|
+
describe('Using a local HTML fixture with jQuery', function() {
|
4
|
+
beforeEach(function() {
|
5
|
+
loadFixtures('index.html');
|
6
|
+
});
|
7
|
+
|
8
|
+
it('can use jQuery against a local fixture', function() {
|
9
|
+
expect($('h1').text()).toBe('Hello World');
|
10
|
+
});
|
11
|
+
});
|