guardian-angel 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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()
@@ -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
@@ -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
@@ -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
@@ -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: []