guardian-angel 0.0.1
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/bin/guardian-angel +13 -0
- data/bin/xctestfile +12 -0
- data/lib/ga_configuration.rb +94 -0
- data/lib/ga_loader.rb +87 -0
- data/lib/ga_logger.rb +32 -0
- data/lib/ga_runner.rb +74 -0
- data/lib/guardian_angel.rb +42 -0
- metadata +80 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: b756688b60516c6856da9c1cff4576f846f52056
|
|
4
|
+
data.tar.gz: d896fceb43a6d3291435f69fab862f073c3f1a4e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 61cea12f91402ba6a541d27a2d8aaa606deea1c2bc954dd0b17f9179cee9ee633179d466283b9428e030156ebb3f0e07087fe708a33369f1304952d3ab7a20b2
|
|
7
|
+
data.tar.gz: 58148addf0594055fd9a76ccff0b8502781bf72f21ee24f8913d69633adad37a8c308cb1f3bc24688d9bd633dd78276f5e1f4ac1961b182f6059bc06a5d77b0c
|
data/bin/guardian-angel
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'ga_loader'
|
|
4
|
+
require 'guardian_angel'
|
|
5
|
+
require 'ga_logger'
|
|
6
|
+
|
|
7
|
+
trap("INT") { exit }
|
|
8
|
+
|
|
9
|
+
configuration = GALoader.readConfiguration()
|
|
10
|
+
|
|
11
|
+
watcher = GuardianAngel.new(configuration)
|
|
12
|
+
watcher.buildTests()
|
|
13
|
+
watcher.watch()
|
data/bin/xctestfile
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'ga_loader'
|
|
4
|
+
require 'ga_runner'
|
|
5
|
+
|
|
6
|
+
trap("INT") { exit }
|
|
7
|
+
|
|
8
|
+
fileToTest = GALoader.getFileFromArgv(ARGV)
|
|
9
|
+
configuration = GALoader.readConfiguration()
|
|
10
|
+
|
|
11
|
+
runner = GARunner.new(configuration, fileToTest)
|
|
12
|
+
runner.test()
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# @author Vittorio Monaco
|
|
2
|
+
class GAConfiguration
|
|
3
|
+
GAConfigurationScheme = "scheme"
|
|
4
|
+
GAConfigurationWorkspace = "workspace"
|
|
5
|
+
GAConfigurationTarget = "target"
|
|
6
|
+
GAConfigurationSuffix = "suffix"
|
|
7
|
+
GAConfigurationReporter = "reporter"
|
|
8
|
+
GAConfigurationXctoolPath = "xctool"
|
|
9
|
+
|
|
10
|
+
# @return the configured xcode scheme
|
|
11
|
+
def scheme
|
|
12
|
+
@scheme
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @return the configured xcode workspace
|
|
16
|
+
def workspace
|
|
17
|
+
@workspace
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return the configured suffix for tests files
|
|
21
|
+
def suffix
|
|
22
|
+
@suffix
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @return the configured xcode tests target
|
|
26
|
+
def target
|
|
27
|
+
@target
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @return the configured xctool reporter
|
|
31
|
+
def reporter
|
|
32
|
+
@reporter
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @return the configured xctool executable path
|
|
36
|
+
def xctool_path
|
|
37
|
+
@xctool_path
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Prints the configuration instance
|
|
41
|
+
# @return a [String] representation of the instance
|
|
42
|
+
def to_s
|
|
43
|
+
hashForOutput = {
|
|
44
|
+
GAConfigurationScheme => @scheme,
|
|
45
|
+
GAConfigurationWorkspace => @workspace,
|
|
46
|
+
GAConfigurationTarget => @target,
|
|
47
|
+
GAConfigurationSuffix => @suffix,
|
|
48
|
+
GAConfigurationReporter => @reporter,
|
|
49
|
+
GAConfigurationXctoolPath => @xctool_path
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return hashForOutput.to_s
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Creates an instance with the given configuration, or uses a default one if not provided
|
|
56
|
+
# @param configuration [GAConfiguration]
|
|
57
|
+
#
|
|
58
|
+
# @note by default the #suffix is implied as "Test", the #reporter as "pretty" and the #xctool_path as "xctool"
|
|
59
|
+
def initialize(configuration = { GAConfigurationSuffix => "Test", GAConfigurationReporter => "pretty", GAConfigurationXctoolPath => "xctool" })
|
|
60
|
+
@scheme = configuration[GAConfigurationScheme]
|
|
61
|
+
@workspace = configuration[GAConfigurationWorkspace]
|
|
62
|
+
@target = configuration[GAConfigurationTarget]
|
|
63
|
+
@suffix = configuration[GAConfigurationSuffix]
|
|
64
|
+
@reporter = configuration[GAConfigurationReporter]
|
|
65
|
+
@xctool_path = configuration[GAConfigurationXctoolPath]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Merges two GAConfiguration instances
|
|
69
|
+
#
|
|
70
|
+
# @param other [GAConfiguration] another instance of GAConfiguration you want to merge
|
|
71
|
+
# @note nil values will not overwrite valid values of self
|
|
72
|
+
def merge(other)
|
|
73
|
+
unless other.scheme.nil?
|
|
74
|
+
@scheme = other.scheme
|
|
75
|
+
end
|
|
76
|
+
unless other.workspace.nil?
|
|
77
|
+
@workspace = other.workspace
|
|
78
|
+
end
|
|
79
|
+
unless other.target.nil?
|
|
80
|
+
@target = other.target
|
|
81
|
+
end
|
|
82
|
+
unless other.suffix.nil?
|
|
83
|
+
@suffix = other.suffix
|
|
84
|
+
end
|
|
85
|
+
unless other.reporter.nil?
|
|
86
|
+
@reporter = other.reporter
|
|
87
|
+
end
|
|
88
|
+
unless other.xctool_path.nil?
|
|
89
|
+
@xctool_path = other.xctool_path
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
return self
|
|
93
|
+
end
|
|
94
|
+
end
|
data/lib/ga_loader.rb
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'ga_logger'
|
|
3
|
+
require 'ga_configuration'
|
|
4
|
+
|
|
5
|
+
CONFIG_FILENAME = 'guardian_angel.json'
|
|
6
|
+
|
|
7
|
+
# @author Vittorio Monaco
|
|
8
|
+
class GALoader
|
|
9
|
+
# Reads the configuration from the file guardian_angel.json
|
|
10
|
+
#
|
|
11
|
+
# @note if the file is not found, it will try to build with default values instead
|
|
12
|
+
# @note this also outputs the final GAConfiguration built on the console
|
|
13
|
+
# (see #GAConfiguration)
|
|
14
|
+
def self.readConfiguration()
|
|
15
|
+
GALogger.log("Reading #{CONFIG_FILENAME}...")
|
|
16
|
+
|
|
17
|
+
configuration = GAConfiguration.new
|
|
18
|
+
|
|
19
|
+
begin
|
|
20
|
+
jsonDictionary = JSON.parse(File.read(CONFIG_FILENAME))
|
|
21
|
+
configurationMerge = GAConfiguration.new(jsonDictionary)
|
|
22
|
+
configuration = configuration.merge(configurationMerge)
|
|
23
|
+
rescue
|
|
24
|
+
#Find workspace, scheme and target
|
|
25
|
+
#merge and return
|
|
26
|
+
GALogger.log("#{CONFIG_FILENAME} not found, using defaults", :Warning)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
validateConfiguration(configuration)
|
|
30
|
+
outputConfiguration(configuration)
|
|
31
|
+
|
|
32
|
+
return configuration
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Validates a given configuration
|
|
36
|
+
#
|
|
37
|
+
# @param configuration [GAConfiguration] the configuration to validate
|
|
38
|
+
# @note required attributes are workspace, scheme and target
|
|
39
|
+
# @note the method will also make sure that the configured xctool executable can be found, or aborts otherwise
|
|
40
|
+
def self.validateConfiguration(configuration)
|
|
41
|
+
if configuration.workspace.nil?
|
|
42
|
+
GALogger.log("workspace was not specified, exiting", :Error)
|
|
43
|
+
abort
|
|
44
|
+
end
|
|
45
|
+
if configuration.scheme.nil?
|
|
46
|
+
GALogger.log("scheme was not specified, exiting", :Error)
|
|
47
|
+
abort
|
|
48
|
+
end
|
|
49
|
+
if configuration.target.nil?
|
|
50
|
+
GALogger.log("target was not specified, exiting", :Error)
|
|
51
|
+
abort
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
xctoolExists = system("which #{configuration.xctool_path} > /dev/null")
|
|
55
|
+
if !xctoolExists
|
|
56
|
+
GALogger.log(configuration.xctool_path + " can't be found. Aborting.", :Error)
|
|
57
|
+
abort
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Outputs a given configuration on the console
|
|
62
|
+
#
|
|
63
|
+
# @param [GAConfiguration] the configuration you want to print
|
|
64
|
+
def self.outputConfiguration(configuration)
|
|
65
|
+
puts configuration.to_s
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Returns a filename from a given array
|
|
69
|
+
#
|
|
70
|
+
# @param argv [Array<String>] an array of strings
|
|
71
|
+
#
|
|
72
|
+
# @note the method will take the last element of the array
|
|
73
|
+
# @note the method will take only the filename if the element of the array is a file, removing the extension and the path
|
|
74
|
+
def self.getFileFromArgv(argv)
|
|
75
|
+
fileToTest = nil
|
|
76
|
+
argv.each do|a|
|
|
77
|
+
fileToTest = File.basename(a, ".*")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
if fileToTest.nil?
|
|
81
|
+
GALogger.log('Failed to get file', :Error)
|
|
82
|
+
abort
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
return fileToTest
|
|
86
|
+
end
|
|
87
|
+
end
|
data/lib/ga_logger.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# @author Vittorio Monaco
|
|
2
|
+
class GALogger
|
|
3
|
+
:Error
|
|
4
|
+
:Warning
|
|
5
|
+
:Success
|
|
6
|
+
:Default
|
|
7
|
+
|
|
8
|
+
# Logs a message on the console
|
|
9
|
+
#
|
|
10
|
+
# @param message [String] a string to log
|
|
11
|
+
# @param type [Symbol] specifies the type of message. This can be :Error, :Warning, :Success or :Default
|
|
12
|
+
# @note depending on the message type, a different color will be used to print the message on the console
|
|
13
|
+
def self.log(message, type = :Default)
|
|
14
|
+
puts sequenceForType(type) + '### ' + message + ' ###' + sequenceForType(:Default)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Returns the character code to print with the right color given a message type
|
|
18
|
+
#
|
|
19
|
+
# @param type [Symbol] the message type. This can be :Error, :Warning, :Success or :Default
|
|
20
|
+
def self.sequenceForType(type)
|
|
21
|
+
case type
|
|
22
|
+
when :Success
|
|
23
|
+
return "\033[32m"
|
|
24
|
+
when :Error
|
|
25
|
+
return "\033[31m"
|
|
26
|
+
when :Warning
|
|
27
|
+
return "\033[33m"
|
|
28
|
+
else
|
|
29
|
+
return "\033[0m"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/ga_runner.rb
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require 'ga_logger'
|
|
2
|
+
require 'guardian_angel'
|
|
3
|
+
|
|
4
|
+
# @author Vittorio Monaco
|
|
5
|
+
class GARunner
|
|
6
|
+
# Creates a new instance given a GAConfiguration object and a filename to run tests
|
|
7
|
+
#
|
|
8
|
+
# @param configuration [GAConfiguration] the configuration you want to use to run the tests (see #GAConfiguration)
|
|
9
|
+
# @param filename [String] the name of the file you want to run the tests for
|
|
10
|
+
# @note filename can also be a tests file
|
|
11
|
+
def initialize(configuration, filename)
|
|
12
|
+
@configuration=configuration
|
|
13
|
+
@filename=filename
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Runs unit tests for the given filename, if a tests file exists
|
|
17
|
+
#
|
|
18
|
+
# @param filename [String] the file you want to run tests for
|
|
19
|
+
# @note filename must be a code file, not a tests file. If you're not sure whether the file is a tests file or not, use #test instead
|
|
20
|
+
# @note if a corresponding tests file cannot be found, outputs a warning line
|
|
21
|
+
def testIfAvailable(filename)
|
|
22
|
+
workspace = @configuration.workspace
|
|
23
|
+
scheme = @configuration.scheme
|
|
24
|
+
target = @configuration.target
|
|
25
|
+
suffix = @configuration.suffix
|
|
26
|
+
reporter = @configuration.reporter
|
|
27
|
+
xctool = @configuration.xctool_path
|
|
28
|
+
|
|
29
|
+
fileExists = system('find . | grep ' + filename + suffix + ' > /dev/null')
|
|
30
|
+
if !fileExists
|
|
31
|
+
GALogger.log(filename + " doesn't seem to have associated tests. You may think about it.", :Warning)
|
|
32
|
+
return
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
GALogger.log("Running tests for file " + filename + '...')
|
|
36
|
+
system(xctool + ' -workspace -workspace ' + workspace + '.xcworkspace' +
|
|
37
|
+
' -scheme ' + scheme +
|
|
38
|
+
' -sdk iphonesimulator' +
|
|
39
|
+
' run-tests' +
|
|
40
|
+
' -reporter ' + reporter
|
|
41
|
+
' only ' + target + ':' + filename + suffix, out: $stdout, err: :out)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Tries to run unit tests for the filename setup during initialization
|
|
45
|
+
#
|
|
46
|
+
# @note if the filename is a tests file, this method strips the tests suffix and runs the tests for the right file instead, after having built the tests project first
|
|
47
|
+
# (see #buildIfNeeded)
|
|
48
|
+
# (see #testIfAvailable)
|
|
49
|
+
def test()
|
|
50
|
+
filename = @filename
|
|
51
|
+
suffix = @configuration.suffix
|
|
52
|
+
|
|
53
|
+
buildIfNeeded()
|
|
54
|
+
if isTest()
|
|
55
|
+
filename = @filename.slice(/(?<file>.*)#{suffix}$/, "file")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
testIfAvailable(filename)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @return true if the filename is a tests file
|
|
62
|
+
def isTest()
|
|
63
|
+
return @filename.end_with? @configuration.suffix
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# This method builds the tests project if the filename setup during initialization is a tests file
|
|
67
|
+
# (see #isTest)
|
|
68
|
+
def buildIfNeeded()
|
|
69
|
+
if isTest()
|
|
70
|
+
GALogger.log(@filename + ' is a test, building all the tests...')
|
|
71
|
+
GuardianAngel.buildWithConfiguration(@configuration)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'ga_logger'
|
|
2
|
+
|
|
3
|
+
# @author Vittorio Monaco
|
|
4
|
+
class GuardianAngel
|
|
5
|
+
# Creates a new instance given a GAConfiguration object
|
|
6
|
+
#
|
|
7
|
+
# @param configuration [GAConfiguration] the configuration you want to use to run the tests (see #GAConfiguration)
|
|
8
|
+
def initialize(configuration)
|
|
9
|
+
@configuration=configuration
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Convenience method to build tests in a stand-alone fashion
|
|
13
|
+
#
|
|
14
|
+
# @param configuration [GAConfiguration] the configuration you want to use to run the tests (see #GAConfiguration)
|
|
15
|
+
def self.buildWithConfiguration(configuration)
|
|
16
|
+
watcher = GuardianAngel.new(configuration)
|
|
17
|
+
watcher.buildTests()
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Builds the tests target through xctool
|
|
21
|
+
#
|
|
22
|
+
# @note a configuration must be already setup for this method to work
|
|
23
|
+
def buildTests()
|
|
24
|
+
workspace = @configuration.workspace
|
|
25
|
+
scheme = @configuration.scheme
|
|
26
|
+
xctool = @configuration.xctool_path
|
|
27
|
+
|
|
28
|
+
GALogger.log("Building workspace " + workspace + " with scheme " + scheme + "...")
|
|
29
|
+
system(xctool + ' -workspace ' + workspace + '.xcworkspace' +
|
|
30
|
+
' -scheme ' + scheme +
|
|
31
|
+
' -sdk iphonesimulator' +
|
|
32
|
+
' build-tests', out: $stdout, err: :out)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Starts watching for changes to .m or .swift files in the caller directory
|
|
36
|
+
#
|
|
37
|
+
# @note this uses the gem filewatcher
|
|
38
|
+
def watch()
|
|
39
|
+
GALogger.log("Watching...")
|
|
40
|
+
system("filewatcher '*.{m,swift}' 'xctestfile $FILENAME'", out: $stdout, err: :out)
|
|
41
|
+
end
|
|
42
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: guardian-angel
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Vittorio Monaco
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2014-11-01 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: filewatcher
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ~>
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0.3'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ~>
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0.3'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: json
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ~>
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.8'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ~>
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.8'
|
|
41
|
+
description: A file watcher that runs tests for the modified files
|
|
42
|
+
email: vittorio.monaco1@gmail.com
|
|
43
|
+
executables:
|
|
44
|
+
- guardian-angel
|
|
45
|
+
- xctestfile
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- bin/guardian-angel
|
|
50
|
+
- bin/xctestfile
|
|
51
|
+
- lib/ga_configuration.rb
|
|
52
|
+
- lib/ga_loader.rb
|
|
53
|
+
- lib/ga_logger.rb
|
|
54
|
+
- lib/ga_runner.rb
|
|
55
|
+
- lib/guardian_angel.rb
|
|
56
|
+
homepage: http://vittoriomonaco.it
|
|
57
|
+
licenses:
|
|
58
|
+
- MIT
|
|
59
|
+
metadata: {}
|
|
60
|
+
post_install_message:
|
|
61
|
+
rdoc_options: []
|
|
62
|
+
require_paths:
|
|
63
|
+
- lib
|
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - '>='
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - '>='
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: '0'
|
|
74
|
+
requirements: []
|
|
75
|
+
rubyforge_project:
|
|
76
|
+
rubygems_version: 2.2.1
|
|
77
|
+
signing_key:
|
|
78
|
+
specification_version: 4
|
|
79
|
+
summary: Guardian Angel
|
|
80
|
+
test_files: []
|