guard-unity 0.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.
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'guard/unity/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'guard-unity'
8
+ spec.version = Guard::UnityVersion::VERSION
9
+ spec.authors = ['Thomas Muntaner']
10
+ spec.email = ['thomas.muntaner@gmail.com']
11
+ spec.description = %q{Guard gem for Unity3D Test Tools}
12
+ spec.summary = %q{guard-unity automatically runs Unity Test Tools on file changes}
13
+ spec.homepage = 'https://github.com/rubyrainbows/guard-unity-test'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_dependency 'guard', '~> 2.0'
21
+ spec.add_dependency 'nokogiri', '~> 1.6'
22
+ spec.add_dependency 'formatador', '~> 0.2'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.3'
25
+ spec.add_development_dependency 'rake', '~> 10.1'
26
+ spec.add_development_dependency 'rspec', '~> 2.14'
27
+ spec.add_development_dependency 'rspec-core', '~> 2.14'
28
+ spec.add_development_dependency 'rspec-mocks', '~> 2.14'
29
+ end
@@ -0,0 +1,45 @@
1
+ require 'guard'
2
+ require 'guard/plugin'
3
+
4
+ module Guard
5
+ class Unity < Plugin
6
+
7
+ require 'guard/unity/runner'
8
+ require 'guard/unity/options'
9
+
10
+ attr_accessor :runner, :options
11
+
12
+ def initialize(options = {})
13
+ super
14
+ @options = Options.with_defaults(options)
15
+ @runner = Runner.new(@options)
16
+ end
17
+
18
+ def start
19
+ _show_start_message
20
+ puts runner.run if _should_test_on_start?
21
+ end
22
+
23
+ def run_on_modifications(paths)
24
+ puts runner.run
25
+ end
26
+
27
+ def reload
28
+ end
29
+
30
+ def run_all
31
+ puts runner.run
32
+ end
33
+
34
+ private
35
+
36
+ def _show_start_message
37
+ ::Guard::UI::info 'Guard::Unity is running'
38
+ end
39
+
40
+ def _should_test_on_start?
41
+ options[:test_on_start]
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,24 @@
1
+ module Guard
2
+ class Unity
3
+ class Notifier
4
+
5
+ require 'guard/unity/notifier/alert'
6
+ require 'guard/unity/notifier/cli'
7
+
8
+ TITLE = 'Unity Tests Results'
9
+
10
+ attr_accessor :alert, :cli
11
+
12
+ def initialize(options={})
13
+ @alert = options[:alert] || Guard::Unity::Notifier::Alert.new
14
+ @cli = options[:cli] || Guard::Unity::Notifier::CLI.new
15
+ end
16
+
17
+ def notify(results)
18
+ alert.notify(results, TITLE)
19
+ cli.notify(results)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ module Guard
2
+ class Unity
3
+ class Notifier
4
+ class Alert
5
+
6
+ def notify(results, title)
7
+ image = _image(results)
8
+ message = _message(results)
9
+ ::Guard::Notifier::notify(message, {title: title, image: image})
10
+ end
11
+
12
+ private
13
+
14
+ def _image(results)
15
+ return :failed if results[:failures] > 0
16
+ return :failed if results[:errors] > 0
17
+ :success
18
+ end
19
+
20
+ def _message(results)
21
+ message = "#{results[:tests]} tests\n"
22
+ message << "#{results[:failures]} failures\n" if results[:failures]
23
+ message << "#{results[:errors]} errors\n" if results[:errors]
24
+ message << "#{results[:ignored]} ignored\n" if results[:ignored]
25
+ message << "#{results[:skipped]} skipped\n" if results[:skipped]
26
+ message << "#{results[:inconclusive]} inconclusive\n" if results[:inconclusive]
27
+ message << "#{results[:invalid]} invalid\n" if results[:invalid]
28
+ message << "#{results[:not_run]} not run\n" if results[:not_run]
29
+ message
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,79 @@
1
+ module Guard
2
+ class Unity
3
+ class Notifier
4
+ class CLI
5
+
6
+ require 'formatador'
7
+
8
+ attr_accessor :formatador
9
+
10
+ SEPARATOR = '-'*100
11
+
12
+ def initialize(options={})
13
+ @formatador = options[:formatador] || Formatador.new
14
+ end
15
+
16
+ def notify(results={})
17
+ cases = results[:test_cases] || []
18
+ table = []
19
+ errors = []
20
+
21
+ cases.each do |test_case|
22
+ table << _row(test_case)
23
+ errors << _error(test_case) if test_case[:failed]
24
+ end
25
+ _display_results results
26
+ _display_table table
27
+ _display_errors errors
28
+ end
29
+
30
+ private
31
+
32
+ def _display_results(results)
33
+ table = [{
34
+ 'Tests' => results[:tests],
35
+ 'Failures' => results[:failures],
36
+ 'Errors' => results[:errors],
37
+ 'Ignored' => results[:ignored],
38
+ 'Skipped' => results[:skipped],
39
+ 'Inconclusive' => results[:inconclusive],
40
+ 'Invalid' => results[:invalid],
41
+ 'Not Run' => results[:not_run]
42
+ }]
43
+ formatador.display_table table, ['Tests', 'Failures', 'Errors', 'Ignored', 'Skipped', 'Inconclusive', 'Invalid', 'Not Run']
44
+ formatador.display_line
45
+ end
46
+
47
+ def _display_table(table)
48
+ formatador.display_table table
49
+ end
50
+
51
+ def _display_errors(errors)
52
+ formatador.display_line
53
+ formatador.display_line SEPARATOR
54
+ formatador.display_line "| [red]Failures[/]"
55
+ formatador.display_line SEPARATOR
56
+ count = 1
57
+ errors.each do |error|
58
+ formatador.display_line
59
+ formatador.display_line "#{count}: #{error[:name]}:\n"
60
+ formatador.display_line "[red]#{error[:message]}[/]\n" unless error[:message] == ""
61
+ formatador.display_line "[red]#{error[:stack]}[/]\n" unless error[:stack] == ""
62
+ formatador.display_line SEPARATOR
63
+ count = count + 1
64
+ end
65
+ end
66
+
67
+ def _row(test_case)
68
+ success = (test_case[:failed]) ? '[red]Failed[/]' : '[green]Success[/]'
69
+ {name: test_case[:name], success: success}
70
+ end
71
+
72
+ def _error(test_case)
73
+ {name: test_case[:name], message: test_case[:message], stack: test_case[:stack]}
74
+ end
75
+
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,26 @@
1
+ module Guard
2
+ class Unity
3
+ module Options
4
+
5
+ DEFAULTS = {
6
+ test_on_start: true,
7
+ project_path: Dir.pwd,
8
+ unity: '/Applications/Unity/Unity.app/Contents/MacOS/Unity',
9
+ results_path: Dir.pwd + '/UnitTestResults.xml'
10
+ }
11
+
12
+ class << self
13
+ def with_defaults(options={})
14
+ opts = DEFAULTS.merge(options)
15
+ opts[:project_path] = clean_directory(opts[:project_path]) # needs to be formatted for cli
16
+ opts
17
+ end
18
+
19
+ def clean_directory(dir)
20
+ dir.gsub(' ', '\ ')
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,64 @@
1
+ module Guard
2
+ class Unity
3
+ class Parser
4
+
5
+ require 'nokogiri'
6
+
7
+ attr_accessor :options, :doc
8
+
9
+ def initialize(options={})
10
+ @options = options
11
+ @doc = nil
12
+ end
13
+
14
+ def parse()
15
+ {
16
+ tests: _get('total'),
17
+ failures: _get('failures'),
18
+ errors: _get('errors'),
19
+ ignored: _get('ignored'),
20
+ not_run: _get('not-run'),
21
+ inconclusive: _get('inconclusive'),
22
+ invalid: _get('invalid'),
23
+ skipped: _get('skipped'),
24
+ test_cases: _testCases
25
+ }
26
+ end
27
+
28
+ private
29
+
30
+ def _get (find)
31
+ doc ||= _getXMLFile
32
+ node = doc.at_xpath("/test-results/@" + find)
33
+ (node == nil) ? 0 : node.value.to_i
34
+ end
35
+
36
+ def _testCases()
37
+ doc ||= _getXMLFile
38
+ nodes = doc.xpath("test-results/test-suite/results/test-case")
39
+ cases = []
40
+
41
+ nodes.each do |node|
42
+ message = node.at_xpath('failure/message') || node.at_xpath('reason/message')
43
+ stack = node.at_xpath('failure/stack-trace') || node.at_xpath('reason/stack-trace')
44
+ cases << {
45
+ name: node['name'],
46
+ failed: (node['success'] == 'False') ? true : false,
47
+ message: (message) ? message.text.gsub("\n",'').strip : "",
48
+ stack: (stack) ? stack.text.gsub("\n",'').strip : ""
49
+ }
50
+ end
51
+
52
+ cases
53
+ end
54
+
55
+ def _getXMLFile()
56
+ f = File.open(options[:results_path])
57
+ doc = Nokogiri::XML(f)
58
+ f.close
59
+ doc
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,45 @@
1
+ module Guard
2
+ class Unity
3
+ class Runner
4
+
5
+ require 'guard/unity/parser'
6
+ require 'guard/unity/notifier'
7
+
8
+ attr_accessor :options, :parser, :notifier
9
+
10
+ def initialize(options = {})
11
+ @options = options
12
+ @parser = options[:parser] || Guard::Unity::Parser.new(options)
13
+ @notifier = options[:notifier] || Guard::Unity::Notifier.new
14
+ end
15
+
16
+ def run
17
+ _run
18
+ end
19
+
20
+ private
21
+
22
+ def _run
23
+ UI.info 'Guard::Unity - Starting Tests. Results will be displayed when finished testing.'
24
+ output = _execute_command _command
25
+ notifier.notify(parser.parse) if $?.success?
26
+ output
27
+ end
28
+
29
+ def _command
30
+ cmd = []
31
+
32
+ cmd << options[:unity]
33
+ cmd << '-projectPath ' + options[:project_path]
34
+ cmd << '-batchmode -executeMethod UnityTest.UnitTestView.RunAllTestsBatch'
35
+
36
+ cmd.join ' '
37
+ end
38
+
39
+ def _execute_command(command)
40
+ %x{#{command}}
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ guard :unity do
2
+ watch(%r{^.*\.cs$})
3
+ end
@@ -0,0 +1,5 @@
1
+ module Guard
2
+ module UnityVersion
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,32 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!--This file represents the results of running a test suite-->
3
+ <test-results name="Unity Tests" total="21" errors="1" failures="2" not-run="2" inconclusive="4" ignored="1" skipped="1" invalid="0">
4
+ <environment />
5
+ <culture-info current-culture="" current-uiculture="" />
6
+ <test-suite name="Unit Tests" type="Assembly" executed="True" result="Failure" success="False" time="0.400">
7
+ <results>
8
+ <test-case name="test 1" executed="True" result="Success" success="True">
9
+ </test-case>
10
+ <test-case name="test 2" executed="True" result="Skipped" success="False">
11
+ <reason>
12
+ <message>
13
+ Message
14
+ </message>
15
+ <stack-trace>
16
+ foo
17
+ </stack-trace>
18
+ </reason>
19
+ </test-case>
20
+ <test-case name="test 3" executed="True" result="Failure" success="False">
21
+ <failure>
22
+ <message>
23
+ Message
24
+ </message>
25
+ <stack-trace>
26
+ foo
27
+ </stack-trace>
28
+ </failure>
29
+ </test-case>
30
+ </results>
31
+ </test-suite>
32
+ </test-results>
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Guard::Unity::Notifier do
4
+
5
+ let (:results) {
6
+ {
7
+ tests: 100,
8
+ errors: 0,
9
+ failures: 0
10
+ }
11
+ }
12
+ let (:subject) { Guard::Unity::Notifier::Alert.new}
13
+
14
+ describe '#notify' do
15
+
16
+ it 'should give a success message' do
17
+ @results = results
18
+ ::Guard::Notifier::should_receive(:notify).with(message(@results), {image: :success, title: Guard::Unity::Notifier::TITLE})
19
+ subject.notify(@results, Guard::Unity::Notifier::TITLE)
20
+ end
21
+
22
+ it 'should give failed message' do
23
+ @results = results.merge(failures: 1)
24
+ ::Guard::Notifier::should_receive(:notify).with(message(@results), {image: :failed, title: Guard::Unity::Notifier::TITLE})
25
+ subject.notify(@results, Guard::Unity::Notifier::TITLE)
26
+ end
27
+
28
+ it 'should give error message' do
29
+ @results = results.merge(errors: 1)
30
+ ::Guard::Notifier::should_receive(:notify).with(message(@results), {image: :failed, title: Guard::Unity::Notifier::TITLE})
31
+ subject.notify(@results, Guard::Unity::Notifier::TITLE)
32
+ end
33
+
34
+ end
35
+
36
+ # taken from the class to make testing easier
37
+ def message(results)
38
+ message = "#{results[:tests]} tests\n"
39
+ message << "#{results[:failures]} failures\n"
40
+ message << "#{results[:errors]} errors\n"
41
+ message
42
+ end
43
+
44
+ end