guard-phpunit2 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +37 -0
- data/LICENSE +19 -0
- data/README.md +106 -0
- data/lib/guard/phpunit2/formatter.rb +64 -0
- data/lib/guard/phpunit2/inspector.rb +54 -0
- data/lib/guard/phpunit2/notifier.rb +68 -0
- data/lib/guard/phpunit2/runner.rb +193 -0
- data/lib/guard/phpunit2/templates/Guardfile +3 -0
- data/lib/guard/phpunit2/version.rb +5 -0
- data/lib/guard/phpunit2.rb +112 -0
- data/spec/fixtures/emptyTest.php +0 -0
- data/spec/fixtures/results/errors.txt +11 -0
- data/spec/fixtures/results/failing.txt +15 -0
- data/spec/fixtures/results/mixed.txt +26 -0
- data/spec/fixtures/results/passing.txt +4 -0
- data/spec/fixtures/results/skipped_and_incomplete.txt +4 -0
- data/spec/fixtures/sampleTest.php +13 -0
- data/spec/guard/phpunit2/formatter_spec.rb +49 -0
- data/spec/guard/phpunit2/inspector_spec.rb +34 -0
- data/spec/guard/phpunit2/notifier_spec.rb +72 -0
- data/spec/guard/phpunit2/runner_spec.rb +168 -0
- data/spec/guard/phpunit2_spec.rb +191 -0
- data/spec/spec_helper.rb +24 -0
- metadata +180 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 25e1c7f4051f51755b045436eacfd314d3d3c561
|
4
|
+
data.tar.gz: ff726d26e443aed564382611d7b730be0e62d15e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 40c41dff5824407ca8bd0dc31c2566da9a2fa23ed4933a2c51f885026d1a846c37affafa9460c37200c3235fc66791bf6334db8fe730d8c93f04b7ab919f9f79
|
7
|
+
data.tar.gz: 4eccfb676173ae0b94d5a16af0fc264df88f080969578c79e52d434ee8b383e70d785a6fe2680ec7f8db9c391f741b495b2e4bf0e281d48daee2b5d99622af5f
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
## 0.1.4 - August 09, 2012
|
2
|
+
|
3
|
+
- [#2][]: Add support for Windows.
|
4
|
+
|
5
|
+
## 0.1.3 - June 15, 2012
|
6
|
+
|
7
|
+
- [#3][]: Support Guard v1.1 API.
|
8
|
+
|
9
|
+
## 0.1.2 - January 26, 2012
|
10
|
+
|
11
|
+
- Fix checking phpunit existence on zsh.
|
12
|
+
- Update Guard to it's first gold release.
|
13
|
+
- Small bug fixes.
|
14
|
+
|
15
|
+
## 0.1.1 - January 03, 2012
|
16
|
+
|
17
|
+
- Update gem dependencies.
|
18
|
+
- Small bug fixes.
|
19
|
+
|
20
|
+
## 0.1.0 - November 30, 2011
|
21
|
+
|
22
|
+
- Add detection for phpunit existence.
|
23
|
+
- Add the `:keep_failed` option.
|
24
|
+
- Add the `:all_after_pass` option.
|
25
|
+
- Refactor a portion of the code and small bug fixes.
|
26
|
+
|
27
|
+
## 0.0.2 - 0.0.3 - November 25, 2011
|
28
|
+
|
29
|
+
- Small bug fixes.
|
30
|
+
|
31
|
+
## 0.0.1 - November 24, 2011
|
32
|
+
|
33
|
+
- Initial release.
|
34
|
+
|
35
|
+
<!--- The following link definition list is generated by PimpMyChangelog --->
|
36
|
+
[#2]: https://github.com/Maher4Ever/guard-phpunit/issues/2
|
37
|
+
[#3]: https://github.com/Maher4Ever/guard-phpunit/issues/3
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (C) 2011 by Maher Sallam
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
Guard::PHPUnit [![Build Status](https://secure.travis-ci.org/Maher4Ever/guard-phpunit.png)](http://travis-ci.org/Maher4Ever/guard-phpunit) [![Dependency Status](https://gemnasium.com/Maher4Ever/guard-phpunit.png?branch=master)](https://gemnasium.com/Maher4Ever/guard-phpunit)
|
2
|
+
==============
|
3
|
+
|
4
|
+
Guard-phpunit allows you to automatically run [PHPUnit][6] tests when sources
|
5
|
+
are modified. It helps with integrating test-driven development (TDD) into
|
6
|
+
your development process: Just launch guard-phpunit before you start working
|
7
|
+
and it will notify you about the status of your tests!
|
8
|
+
|
9
|
+
*Note*: Although guard-phpunit should work with any [PHP][7] version [PHPUnit][6] supports,
|
10
|
+
it has only been tested on [PHP][7] 5.3.8 and 5.4.4.
|
11
|
+
|
12
|
+
Install
|
13
|
+
-------
|
14
|
+
|
15
|
+
Please be sure to have [PHP][7], [PHPUnit][6] and [Ruby][1] installed on your machine before
|
16
|
+
you proceed with the installation.
|
17
|
+
|
18
|
+
The latest versions of [Ruby][1] come with a packages-manager called `gem`. `gem` can be used to
|
19
|
+
install various packages, including guard-phpunit.
|
20
|
+
|
21
|
+
To install guard-phpunit, run the following command in the terminal:
|
22
|
+
|
23
|
+
```shell
|
24
|
+
$ gem install guard-phpunit
|
25
|
+
```
|
26
|
+
|
27
|
+
Usage
|
28
|
+
-----
|
29
|
+
|
30
|
+
Please read the [Guard usage documentation][3].
|
31
|
+
|
32
|
+
Guardfile
|
33
|
+
---------
|
34
|
+
|
35
|
+
Guard-phpunit can be used with any kind of [PHP][7] projects that uses PHPUnit as
|
36
|
+
its testing framwork. Please read the [Guard documentation][3] for more information
|
37
|
+
about the Guardfile DSL.
|
38
|
+
|
39
|
+
By default, guard-phpunit will use the current working directory (pwd) to
|
40
|
+
search for tests and run them on start (if you enabled the `:all_on_start` option).
|
41
|
+
|
42
|
+
### Example PHP project
|
43
|
+
|
44
|
+
The [PHPUnit documentaion][4] uses the [Object Freezer][5] library as an example on how
|
45
|
+
to organize tests. This project uses the `Tests` directory for its tests.
|
46
|
+
|
47
|
+
An example of the Guardfile for the same project would look
|
48
|
+
something like:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
guard 'phpunit', :tests_path => 'Tests', :cli => '--colors' do
|
52
|
+
# Watch tests files
|
53
|
+
watch(%r{^.+Test\.php$})
|
54
|
+
|
55
|
+
# Watch library files and run their tests
|
56
|
+
watch(%r{^Object/(.+)\.php}) { |m| "Tests/#{m[1]}Test.php" }
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
Options
|
61
|
+
-------
|
62
|
+
|
63
|
+
The following options can be passed to Guard::PHPUnit:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
:all_on_start => false # Run all tests on startup.
|
67
|
+
# default: true
|
68
|
+
|
69
|
+
:all_after_pass => false # Run all tests after changed tests pass. This ensures
|
70
|
+
# that the process of making changed tests pass didn't
|
71
|
+
# break something else.
|
72
|
+
# default: true
|
73
|
+
|
74
|
+
:keep_failed => false # Remember failed tests and keep running them with
|
75
|
+
# each change until they pass.
|
76
|
+
# default: true
|
77
|
+
|
78
|
+
:tests_path => 'tests' # Relative path to the tests directory. This path
|
79
|
+
# is used when running all the tests.
|
80
|
+
# default: the current working directory (pwd)
|
81
|
+
|
82
|
+
:cli => '--colors' # The options passed to the phpunit command
|
83
|
+
# when running the tests.
|
84
|
+
# default: nil
|
85
|
+
```
|
86
|
+
|
87
|
+
Development
|
88
|
+
-----------
|
89
|
+
|
90
|
+
* Source hosted at [GitHub](https://github.com/Maher4Ever/guard-phpunit)
|
91
|
+
* Report issues/Questions/Feature requests on [GitHub Issues](https://github.com/Maher4Ever/guard-phpunit/issues)
|
92
|
+
|
93
|
+
Pull requests are very welcome! Make sure your patches are well tested. Please create a topic branch for every separate change
|
94
|
+
you make.
|
95
|
+
|
96
|
+
Author
|
97
|
+
------
|
98
|
+
|
99
|
+
[Maher Sallam](https://github.com/Maher4Ever)
|
100
|
+
|
101
|
+
[1]:http://ruby-lang.org
|
102
|
+
[3]:https://github.com/guard/guard#readme
|
103
|
+
[4]:http://www.phpunit.de/manual/current/en/
|
104
|
+
[5]:https://github.com/sebastianbergmann/php-object-freezer/
|
105
|
+
[6]:http://www.phpunit.de
|
106
|
+
[7]:http://php.net
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Guard
|
2
|
+
class PHPUnit2
|
3
|
+
|
4
|
+
# The Guard::PHPUnit formatter parses the output
|
5
|
+
# of phpunit which gets printed by the progress
|
6
|
+
# printer.
|
7
|
+
#
|
8
|
+
module Formatter
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# Parses the tests output.
|
12
|
+
#
|
13
|
+
# @param [String] text the output of phpunit.
|
14
|
+
# @return [Hash] the parsed results
|
15
|
+
#
|
16
|
+
def parse_output(text)
|
17
|
+
results = {
|
18
|
+
:tests => look_for_words_in('test', text),
|
19
|
+
:failures => look_for_words_in('failure', text),
|
20
|
+
:errors => look_for_words_in('error', text),
|
21
|
+
:pending => look_for_words_in(['skipped', 'incomplete'], text),
|
22
|
+
:duration => look_for_duration_in(text)
|
23
|
+
}
|
24
|
+
results.freeze
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Searches for a list of strings in the tests output
|
30
|
+
# and returns the total number assigned to these strings.
|
31
|
+
#
|
32
|
+
# @param [String, Array<String>] string_list the words
|
33
|
+
# @param [String] text the tests output
|
34
|
+
# @return [Integer] the total number assigned to the words
|
35
|
+
#
|
36
|
+
def look_for_words_in(strings_list, text)
|
37
|
+
count = 0
|
38
|
+
strings_list = Array(strings_list)
|
39
|
+
strings_list.each do |s|
|
40
|
+
text =~ %r{
|
41
|
+
(\d+) # count of what we are looking for
|
42
|
+
[ ] # then a space
|
43
|
+
#{s}s? # then the string
|
44
|
+
.* # then whatever
|
45
|
+
\Z # start looking at the end of the text
|
46
|
+
}x
|
47
|
+
count += $1.to_i unless $1.nil?
|
48
|
+
end
|
49
|
+
count
|
50
|
+
end
|
51
|
+
|
52
|
+
# Searches for the duration in the tests output
|
53
|
+
#
|
54
|
+
# @param [String] text the tests output
|
55
|
+
# @return [Integer] the duration
|
56
|
+
#
|
57
|
+
def look_for_duration_in(text)
|
58
|
+
text =~ %r{Finished in (\d)+ seconds?.*\Z}m
|
59
|
+
$1.nil? ? 0 : $1.to_i
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Guard
|
2
|
+
class PHPUnit2
|
3
|
+
|
4
|
+
# The Guard::PHPUnit inspector verfies that the changed paths
|
5
|
+
# are valid for Guard::PHPUnit.
|
6
|
+
#
|
7
|
+
module Inspector
|
8
|
+
class << self
|
9
|
+
|
10
|
+
attr_accessor :tests_path
|
11
|
+
|
12
|
+
# Clean the changed paths and return only valid
|
13
|
+
# PHPUnit tests files.
|
14
|
+
#
|
15
|
+
# @param [Array<String>] paths the changed paths
|
16
|
+
# @return [Array<String>] the valid tests files
|
17
|
+
#
|
18
|
+
def clean(paths)
|
19
|
+
paths.uniq!
|
20
|
+
paths.compact!
|
21
|
+
paths = paths.select { |p| test_file?(p) }
|
22
|
+
clear_tests_files_list
|
23
|
+
paths
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Checks if the paths is a valid test file.
|
29
|
+
#
|
30
|
+
# @param [String] path the test path
|
31
|
+
# @return [Boolean] whether the path a valid test or not
|
32
|
+
#
|
33
|
+
def test_file?(path)
|
34
|
+
tests_files.include?(path)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Scans the tests path and keeps a list of all
|
38
|
+
# tests paths.
|
39
|
+
#
|
40
|
+
def tests_files
|
41
|
+
@tests_files ||= Dir.glob( File.join(tests_path, '**', '*Test.php') )
|
42
|
+
end
|
43
|
+
|
44
|
+
# Clears the list of PHPUnit tests.
|
45
|
+
#
|
46
|
+
# @see #clean
|
47
|
+
#
|
48
|
+
def clear_tests_files_list
|
49
|
+
@tests_files = nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Guard
|
2
|
+
class PHPUnit2
|
3
|
+
|
4
|
+
# The Guard::PHPUnit notifier displays a notification pop-up
|
5
|
+
# with the tests results.
|
6
|
+
#
|
7
|
+
module Notifier
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# Displays a system notification.
|
11
|
+
#
|
12
|
+
# @param [String] message the message to show
|
13
|
+
# @param [Hash] options the notifier options
|
14
|
+
#
|
15
|
+
def notify(message, options)
|
16
|
+
::Guard::Notifier.notify(message, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Displays a notification about the tests results.
|
20
|
+
#
|
21
|
+
# @param [Hash] test_results the parsed tests results
|
22
|
+
# @option test_results [Integer] :tests tests count
|
23
|
+
# @option test_results [Integer] :failures failures count
|
24
|
+
# @option test_results [Integer] :errors count count
|
25
|
+
# @option test_results [Integer] :pending pending tests count
|
26
|
+
# @option test_results [Integer] :duration tests duration
|
27
|
+
#
|
28
|
+
def notify_results(test_results)
|
29
|
+
notify(message(test_results), {
|
30
|
+
:title => 'PHPUnit results',
|
31
|
+
:image => image(test_results)
|
32
|
+
})
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Formats the message for the tests results notifier.
|
38
|
+
#
|
39
|
+
# @param (see .notify)
|
40
|
+
# @return [String] the message
|
41
|
+
#
|
42
|
+
def message(results)
|
43
|
+
message = "#{results[:tests]} tests, #{results[:failures]} failures"
|
44
|
+
message << "\n#{results[:errors]} errors" if results[:errors] > 0
|
45
|
+
message << " (#{results[:pending]} pending)" if results[:pending] > 0
|
46
|
+
message << "\nin #{results[:duration]} seconds"
|
47
|
+
message
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the appropriate image for the tests results.
|
51
|
+
#
|
52
|
+
# @param (see .notify)
|
53
|
+
# @return [Symbol] the image symbol
|
54
|
+
#
|
55
|
+
def image(results)
|
56
|
+
case
|
57
|
+
when results[:failures] + results[:errors] > 0
|
58
|
+
:failed
|
59
|
+
when results[:pending] > 0
|
60
|
+
:pending
|
61
|
+
else
|
62
|
+
:success
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Guard
|
5
|
+
class PHPUnit2
|
6
|
+
|
7
|
+
# The Guard::PHPUnit runner handles running the tests, displaying
|
8
|
+
# their output and notifying the user about the results.
|
9
|
+
#
|
10
|
+
module Runner
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# The exittcode phpunit returns when the tests contain failures
|
14
|
+
#
|
15
|
+
PHPUNIT_FAILURES_EXITCODE = 1
|
16
|
+
|
17
|
+
# The exittcode phpunit returns when the tests contain errors
|
18
|
+
#
|
19
|
+
PHPUNIT_ERRORS_EXITCODE = 2
|
20
|
+
|
21
|
+
# Runs the PHPUnit tests and displays notifications
|
22
|
+
# about the results.
|
23
|
+
#
|
24
|
+
# @param [Array<Strings>] path to the tests files.
|
25
|
+
# @param (see PHPUnit#initialize)
|
26
|
+
# @return [Boolean] whether the tests were run successfully
|
27
|
+
#
|
28
|
+
def run(paths, options = {})
|
29
|
+
paths = Array(paths)
|
30
|
+
|
31
|
+
return false if paths.empty?
|
32
|
+
|
33
|
+
unless phpunit_exists?
|
34
|
+
UI.error('phpunit is not installed on your machine.', :reset => true)
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
|
38
|
+
run_tests(paths, options)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Checks that phpunit is installed on the user's
|
44
|
+
# machine.
|
45
|
+
#
|
46
|
+
# @return [Boolean] The status of phpunit
|
47
|
+
#
|
48
|
+
def phpunit_exists?
|
49
|
+
`phpunit --version`
|
50
|
+
true
|
51
|
+
rescue Errno::ENOENT
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
# Executes the testing command on the tests
|
56
|
+
# and returns the status of this process.
|
57
|
+
#
|
58
|
+
# @param (see #run)
|
59
|
+
# @param (see #run)
|
60
|
+
#
|
61
|
+
def run_tests(paths, options)
|
62
|
+
|
63
|
+
notify_start(paths, options)
|
64
|
+
|
65
|
+
if paths.length == 1
|
66
|
+
tests_path = paths.first
|
67
|
+
output = execute_command phpunit_command(tests_path, options)
|
68
|
+
else
|
69
|
+
create_tests_folder_for(paths) do |tests_folder|
|
70
|
+
output = execute_command phpunit_command(tests_folder, options)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# print the output to the terminal
|
75
|
+
UI.info output
|
76
|
+
|
77
|
+
# return false in case the system call fails with no status!
|
78
|
+
return false if $?.nil?
|
79
|
+
|
80
|
+
if $?.success? or tests_contain_failures? or tests_contain_errors?
|
81
|
+
notify_results(output, options)
|
82
|
+
else
|
83
|
+
notify_failure(options)
|
84
|
+
end
|
85
|
+
|
86
|
+
$?.success?
|
87
|
+
end
|
88
|
+
|
89
|
+
# Displays the start testing notification.
|
90
|
+
#
|
91
|
+
# @param (see #run)
|
92
|
+
# @param (see #run)
|
93
|
+
#
|
94
|
+
def notify_start(paths, options)
|
95
|
+
message = options[:message] || "Running: #{paths.join(' ')}"
|
96
|
+
UI.info(message, :reset => true)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Displays a notification about the tests results.
|
100
|
+
#
|
101
|
+
# @param [String] output the tests output
|
102
|
+
# @param (see #run)
|
103
|
+
#
|
104
|
+
def notify_results(output, options)
|
105
|
+
return if options[:notification] == false
|
106
|
+
results = Formatter.parse_output(output)
|
107
|
+
Notifier.notify_results(results)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Displays a notification about failing to run the tests
|
111
|
+
#
|
112
|
+
# @param (see #run)
|
113
|
+
#
|
114
|
+
def notify_failure(options)
|
115
|
+
return if options[:notification] == false
|
116
|
+
Notifier.notify('Failed! Check the console', :title => 'PHPUnit results', :image => :failed)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Checks the exitstatus of the phpunit command
|
120
|
+
# for a sign of failures in the tests.
|
121
|
+
#
|
122
|
+
# @return [Boolean] whether the tests contain failures or not
|
123
|
+
#
|
124
|
+
def tests_contain_failures?
|
125
|
+
$?.exitstatus == PHPUNIT_FAILURES_EXITCODE
|
126
|
+
end
|
127
|
+
|
128
|
+
# Checks the exitstatus of the phpunit command
|
129
|
+
# for a sign of errors in the tests.
|
130
|
+
#
|
131
|
+
# @return [Boolean] whether the tests contain errors or not
|
132
|
+
#
|
133
|
+
def tests_contain_errors?
|
134
|
+
$?.exitstatus == PHPUNIT_ERRORS_EXITCODE
|
135
|
+
end
|
136
|
+
|
137
|
+
# Creates a temporary folder which has links to
|
138
|
+
# the tests paths. This method is used because PHPUnit
|
139
|
+
# can't run multiple tests files at the same time and generate
|
140
|
+
# one result for them.
|
141
|
+
#
|
142
|
+
# @param (see #run)
|
143
|
+
# @yield [String] d the temporary dir for the tests
|
144
|
+
#
|
145
|
+
def create_tests_folder_for(paths)
|
146
|
+
Dir.mktmpdir('guard_phpunit') do |d|
|
147
|
+
symlink_paths_to_tests_folder(paths, d)
|
148
|
+
yield d
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Creates symbolic links inside the folder pointing
|
153
|
+
# back to the paths.
|
154
|
+
#
|
155
|
+
# @see #create_tests_folder_for
|
156
|
+
#
|
157
|
+
# @param (see #run)
|
158
|
+
# @param [String] the folder in which the links must be made
|
159
|
+
#
|
160
|
+
def symlink_paths_to_tests_folder(paths, folder)
|
161
|
+
paths.each do |p|
|
162
|
+
FileUtils.mkdir_p( File.join(folder, File.dirname(p) ) ) unless File.dirname(p) == '.'
|
163
|
+
FileUtils.ln_s(Pathname.new(p).realpath, File.join(folder, p))
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Generates the phpunit command for the tests paths.
|
168
|
+
#
|
169
|
+
# @param (see #run)
|
170
|
+
# @param (see #run)
|
171
|
+
# @see #run_tests
|
172
|
+
#
|
173
|
+
def phpunit_command(path, options)
|
174
|
+
cmd_parts = []
|
175
|
+
cmd_parts << "phpunit"
|
176
|
+
cmd_parts << options[:cli] if options[:cli]
|
177
|
+
cmd_parts << path
|
178
|
+
|
179
|
+
cmd_parts.join(' ')
|
180
|
+
end
|
181
|
+
|
182
|
+
# Executes a system command and returns the output.
|
183
|
+
#
|
184
|
+
# @param [String] command the command to be run
|
185
|
+
# @return [String] the output of the executed command
|
186
|
+
#
|
187
|
+
def execute_command(command)
|
188
|
+
%x{#{command}}
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'guard'
|
2
|
+
require 'guard/guard'
|
3
|
+
|
4
|
+
module Guard
|
5
|
+
|
6
|
+
# The PHPUnit guard gets notified about system
|
7
|
+
# events.
|
8
|
+
#
|
9
|
+
class PHPUnit2 < Guard
|
10
|
+
|
11
|
+
autoload :Inspector, 'guard/phpunit2/inspector'
|
12
|
+
autoload :Formatter, 'guard/phpunit2/formatter'
|
13
|
+
autoload :Notifier, 'guard/phpunit2/notifier'
|
14
|
+
autoload :Runner, 'guard/phpunit2/runner'
|
15
|
+
|
16
|
+
DEFAULT_OPTIONS = {
|
17
|
+
:all_on_start => true,
|
18
|
+
:all_after_pass => true,
|
19
|
+
:keep_failed => true,
|
20
|
+
:cli => nil,
|
21
|
+
:tests_path => Dir.pwd
|
22
|
+
}
|
23
|
+
|
24
|
+
# Initialize Guard::PHPUnit.
|
25
|
+
#
|
26
|
+
# @param [Array<Guard::Watcher>] watchers the watchers in the Guard block
|
27
|
+
# @param [Hash] options the options for the Guard
|
28
|
+
# @option options [Boolean] :all_on_start run all tests on start
|
29
|
+
# @option options [Boolean] :all_after_pass run all tests after failed tests pass
|
30
|
+
# @option options [Boolean] :keep_failed remember failed tests or not
|
31
|
+
# @option options [String] :cli The CLI arguments passed to phpunit
|
32
|
+
# @option options [String] :tests_path the path where all tests exist
|
33
|
+
#
|
34
|
+
def initialize(watchers = [], options = {})
|
35
|
+
defaults = DEFAULT_OPTIONS.clone
|
36
|
+
@options = defaults.merge(options)
|
37
|
+
super(watchers, @options)
|
38
|
+
|
39
|
+
@failed_paths = []
|
40
|
+
@previous_failed = false
|
41
|
+
|
42
|
+
Inspector.tests_path = @options[:tests_path]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Gets called once when Guard starts.
|
46
|
+
#
|
47
|
+
# @raise [:task_has_failed] when stop has failed
|
48
|
+
#
|
49
|
+
def start
|
50
|
+
run_all if options[:all_on_start]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Gets called when all tests should be run.
|
54
|
+
#
|
55
|
+
# @raise (see #start)
|
56
|
+
#
|
57
|
+
def run_all
|
58
|
+
success = Runner.run(options[:tests_path], options.merge(
|
59
|
+
:message => 'Running all tests'
|
60
|
+
))
|
61
|
+
|
62
|
+
@previous_failed = !success
|
63
|
+
throw :task_has_failed unless success
|
64
|
+
end
|
65
|
+
|
66
|
+
# Gets called when the watched tests have changes.
|
67
|
+
#
|
68
|
+
# @param [Array<String>] paths to the changed tests
|
69
|
+
# @raise (see #start)
|
70
|
+
#
|
71
|
+
def run_on_changes(paths)
|
72
|
+
paths = Inspector.clean(paths + @failed_paths)
|
73
|
+
success = Runner.run(paths, options)
|
74
|
+
|
75
|
+
update_failed_paths(success, paths)
|
76
|
+
run_all_after_pass(success)
|
77
|
+
throw :task_has_failed unless success
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
# Adds or removes path to the failed_paths bassed
|
83
|
+
# on the tests result.
|
84
|
+
#
|
85
|
+
# @param [Boolean] tests_passed whether the tests passed or not
|
86
|
+
# @param [Array<String>] paths the tests paths
|
87
|
+
#
|
88
|
+
def update_failed_paths(tests_passed, paths)
|
89
|
+
return unless @options[:keep_failed]
|
90
|
+
|
91
|
+
if tests_passed
|
92
|
+
@failed_paths -= paths
|
93
|
+
else
|
94
|
+
@failed_paths += paths
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Runs all tests after the failed tests pass.
|
99
|
+
#
|
100
|
+
# @param (see .update_failed_paths)
|
101
|
+
#
|
102
|
+
def run_all_after_pass(tests_passed)
|
103
|
+
return unless @options[:all_after_pass]
|
104
|
+
|
105
|
+
if tests_passed
|
106
|
+
run_all if @previous_failed
|
107
|
+
else
|
108
|
+
@previous_failed = true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
File without changes
|
@@ -0,0 +1,11 @@
|
|
1
|
+
E
|
2
|
+
|
3
|
+
Errors:
|
4
|
+
|
5
|
+
1) NumberTest::testMathStillWorks
|
6
|
+
NumberException: Division by zero!
|
7
|
+
# /home/maher/Projects/php/PHPUnit-Progress/Tests/_files/Number.php:61
|
8
|
+
# /home/maher/Projects/php/PHPUnit-Progress/Tests/_files/NumberTest.php:81
|
9
|
+
|
10
|
+
Finished in 0 seconds
|
11
|
+
1 test, 0 assertions, 1 errors
|