specss 1.0.0

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
+ SHA256:
3
+ metadata.gz: 62e0dda02c8ae2b19b17707496db1b5074ffdd0cb592ace3ca41e09b715f52e3
4
+ data.tar.gz: acce2bed54b8bde82ba941ea4e968633c53237fce1345731bd09ba86b58a5e40
5
+ SHA512:
6
+ metadata.gz: e71febd9e68f475df1d9e46bccddbc813b21e8d6c8824d6f30cdaa2a72938253e50f498b9f6be2d37e5798618487578eeb302ea25b878d253601c41c88c54db1
7
+ data.tar.gz: a6b638d032f2bd789e4b94a4efb75a65c52702ae99dd41e7a930ac502112ca12c769cd4addd00dd529843ef920f13997990f95b9eacc7e1282cd84539d2176b9
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_STORE
2
+ Gemfile.lock
3
+ /builds
4
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ gemspec
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # Smarter Rspec Runner
2
+ Script that runs specs for Spectra Rails projects based off of dependencies and perforce changelists
3
+
4
+ ### Gathering Dependents
5
+ In the script I utilize the [Rubrowser](https://github.com/emad-elsaid/rubrowser) gem to create a dependency graph for the code.
6
+
7
+ ### Installation
8
+ This gem is publicly available on RubyGems.
9
+ ```
10
+ gem install specss
11
+ ```
12
+ If your projects use different Ruby versions, then each one will require this step in order to run.
13
+
14
+ ### Use
15
+ Navigate to the root of your rails app or ruby project and simply run:
16
+
17
+ ```
18
+ specss
19
+ ```
20
+
21
+ By default, it only runs the 'lite' version that executes specs based on your p4 status. To run specs on all changed files and
22
+ all dependents of those changed files, run:
23
+
24
+ ```
25
+ specss -e
26
+ ```
27
+
28
+ For other information, print the help after running the executable:
29
+
30
+ ```
31
+ [~]$ specss -h
32
+ Usage: specss [option]
33
+ -e, --extended Run specs of modified files and dependents
34
+ -l, --lite Run specs of modified files only
35
+ -v, --version Smarter Specs Version
36
+ -h, --help Prints this help
37
+ ```
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+ # Auto load gem into ruby console
9
+ task :console do
10
+ exec "irb -r specss -I ./lib"
11
+ end
12
+
13
+
data/bin/specss ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'specss'
5
+ require 'specss/executor'
6
+
7
+ ARGV << '-l' if ARGV.empty? # Default to lite if no arguments are passed
8
+
9
+ Options = Struct.new(:name)
10
+
11
+ ##
12
+ # Parse arguments that are passed when running specs
13
+ class Parser
14
+ def self.parse(options)
15
+
16
+ opt_parser = OptionParser.new do |opts|
17
+ opts.banner = "Usage: specss [option]"
18
+
19
+ opts.on("-e", "--extended", "Run specs of modified files and dependents") do |n|
20
+ Executor.main('extended')
21
+ end
22
+
23
+ opts.on("-l", "--lite", "Run specs of modified files only") do |n|
24
+ Executor.main('lite')
25
+ end
26
+
27
+ opts.on("-v", "--version", "Smarter Specs Version") do |n|
28
+ puts "Specss #{Specss::VERSION}"
29
+ end
30
+
31
+ opts.on("-h", "--help", "Prints this help") do
32
+ puts opts
33
+ exit
34
+ end
35
+ end
36
+
37
+ opt_parser.parse!(options)
38
+ end
39
+ end
40
+
41
+ begin
42
+ Parser.parse(ARGV)
43
+ rescue OptionParser::InvalidOption
44
+ puts "Warning: Invalid option"
45
+ exec("specss -h")
46
+ end
@@ -0,0 +1,63 @@
1
+ require 'specss/files'
2
+
3
+ module Executor
4
+ class << self
5
+
6
+ ##
7
+ # Takes in option from parse and executes main functions
8
+ def main(opt)
9
+ $changed_files = Files::Perforce.get_changelist_files
10
+
11
+ # Pass in options from ARGV on whether to run lite or extended
12
+ case opt
13
+ when 'extended'
14
+ specs_to_run = extended
15
+ else
16
+ specs_to_run = lite
17
+ end
18
+
19
+ if specs_to_run.empty?
20
+ puts 'No specs need to be run'
21
+ else
22
+ spec_names = Files::Specs.chop_file_paths(specs_to_run)
23
+ puts 'Running specs: ' + spec_names.join(" ")
24
+ exec "bundle exec rspec " + specs_to_run.join(" ")
25
+ end
26
+ end
27
+
28
+ ##
29
+ # Returns all unique files in changelist and their dependents
30
+ def get_all_affected_files
31
+ all_files = $changed_files
32
+ dependents = get_dependents
33
+
34
+ dependents.each do |d|
35
+ all_files.push(d) unless all_files.include? d
36
+ end
37
+ all_files
38
+ end
39
+
40
+ ##
41
+ # Returns all dependents of files in changelist
42
+ def get_dependents
43
+ dependents = []
44
+ $changed_files.each do |f|
45
+ dependents_array = Files::Dependencies.get_dependencies(f)
46
+ dependents_array.each do |d|
47
+ dependents.push(d) unless dependents.include? d
48
+ end
49
+ end
50
+ dependents
51
+ end
52
+
53
+ def extended
54
+ all_files = get_all_affected_files
55
+ Files::Specs.get_specs(all_files)
56
+ end
57
+
58
+ def lite
59
+ Files::Specs.get_specs($changed_files)
60
+ end
61
+ end
62
+
63
+ end
@@ -0,0 +1,81 @@
1
+ module Files
2
+ require 'json'
3
+
4
+ module Perforce
5
+ ##
6
+ # Returns all ruby files in changelist as an array of files without extension
7
+ def self.get_changelist_files
8
+ changed_files = []
9
+ p4_status = %x|p4 status &|
10
+ p4_array = p4_status.split("\n")
11
+
12
+ # Add all ruby files ready to be submitted to changed file array
13
+ p4_array.each do |p|
14
+ next unless p.include?('.rb')
15
+ file = p.split(' - ')[0]
16
+ status = p.split(' - ')[1]
17
+ changed_files.push(File.basename(file, ".*")) if status.include? 'submit'
18
+ end
19
+ changed_files
20
+ end
21
+ end
22
+
23
+ module Dependencies
24
+ ##
25
+ # Takes in a file and returns all files that are dependents as an array of files without extension
26
+ def self.get_dependencies(file)
27
+ dependents = []
28
+ # Get file name without extension and convert to camel case
29
+ basename = File.basename(file, ".*")
30
+ basename = basename.gsub(/(?:^|_)([a-z])/) do $1.upcase end
31
+
32
+ # Get rubrowser output and parse for the relation data
33
+ output = %x|rubrowser &|
34
+ data = output.match(/var\s+data\s+=\s+(.*?);/m)[1].split('</script>')[0]
35
+ data_hash = JSON.parse(data)
36
+ relations = data_hash['relations']
37
+
38
+ # Return dependents of input file
39
+ dependents_data = relations.select { |i| i['resolved_namespace'] == basename }
40
+ dependents_data.each do |d|
41
+ filename = d['file']
42
+ basename = File.basename(filename, ".*")
43
+ next if basename.include? '_spec'
44
+ dependents.push(basename) unless dependents.include? basename
45
+ end
46
+ dependents
47
+ end
48
+ end
49
+
50
+ module Specs
51
+ ##
52
+ # Returns all specs to run as an array of file paths relative to root
53
+ def self.get_specs(changed_files)
54
+ specs_to_run = []
55
+ specs = Dir.glob('spec/**/*').select{ |e| File.file? e }
56
+
57
+ # Check if each spec is included in the list of changed files
58
+ specs.each do |s|
59
+ spec_name = File.basename(s, ".*")
60
+ spec_name.slice! '_spec' if spec_name.include? '_spec'
61
+ next if spec_name.include? 'shared_examples'
62
+ specs_to_run.push(s) if changed_files.include? spec_name
63
+ end
64
+ specs_to_run
65
+ end
66
+
67
+ ##
68
+ # Returns array of specs to run with the absolute path chopped off
69
+ def self.chop_file_paths(specs)
70
+ specs_to_run = []
71
+
72
+ specs.each do |s|
73
+ spec_name = File.basename(s)
74
+ specs_to_run.push(spec_name)
75
+ end
76
+ specs_to_run
77
+ end
78
+ end
79
+
80
+ end
81
+
@@ -0,0 +1,3 @@
1
+ module Specss
2
+ VERSION = '1.0.0'
3
+ end
data/lib/specss.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'specss/version'
2
+ require 'specss/executor'
3
+
4
+ module Specss
5
+ end
data/specss.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'specss/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'specss'
7
+ s.version = Specss::VERSION
8
+ s.authors = ['Tom Bonan']
9
+ s.email = ['tombonan@spectralogic.com']
10
+ s.homepage = 'https://github.com/tombonan/smarter-specs'
11
+ s.summary = 'A smarter Rspec Runner'
12
+ s.description = 'A smarter Rspec Runner'
13
+ s.license = 'MIT'
14
+
15
+ s.files = `git ls-files -z`.split("\x0").reject do |f|
16
+ f.match(%r{^(test|spec|features)/})
17
+ end
18
+
19
+ s.bindir = 'bin'
20
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ s.require_paths = ['lib']
22
+
23
+ s.add_runtime_dependency 'rubrowser', '~> 2.0.0'
24
+
25
+ s.post_install_message = "Welcome to the Spec Party"
26
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: specss
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Tom Bonan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-10-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rubrowser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.0
27
+ description: A smarter Rspec Runner
28
+ email:
29
+ - tombonan@spectralogic.com
30
+ executables:
31
+ - specss
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".gitignore"
36
+ - Gemfile
37
+ - README.md
38
+ - Rakefile
39
+ - bin/specss
40
+ - lib/specss.rb
41
+ - lib/specss/executor.rb
42
+ - lib/specss/files.rb
43
+ - lib/specss/version.rb
44
+ - specss.gemspec
45
+ homepage: https://github.com/tombonan/smarter-specs
46
+ licenses:
47
+ - MIT
48
+ metadata: {}
49
+ post_install_message: Welcome to the Spec Party
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubygems_version: 3.0.3
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: A smarter Rspec Runner
68
+ test_files: []