command_test 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ == 0.0.1 2010-08-25
2
+
3
+ * Hi.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 George Ogata
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,109 @@
1
+ # Command Test
2
+
3
+ Test that your app runs or does not run commands.
4
+
5
+ ## Why?
6
+
7
+ Ruby has a bucket of ways to run commands:
8
+
9
+ * Kernel#system
10
+ * Kernel#`
11
+ * Kernel.open
12
+ * IO.popen
13
+ * Open3.popen3
14
+
15
+ Mocking becomes impractical because you seldom care *how* a command is
16
+ run, just that it *is* run (or not run). Methods that run the command
17
+ through the shell are also tricky to mock correctly, as extra shell
18
+ syntax can easily throw off the test.
19
+
20
+ ## How
21
+
22
+ ### RSpec
23
+
24
+ lambda do
25
+ ...
26
+ end.should run_command('convert', 'bad.gif', 'good.png')
27
+
28
+ ### Test::Unit
29
+
30
+ assert_runs_command 'convert', 'bad.gif', 'good.png' do
31
+ ...
32
+ end
33
+
34
+ assert_does_not_run_command 'convert', 'bad.gif', 'good.png' do
35
+ ...
36
+ end
37
+
38
+ ### Other frameworks
39
+
40
+ Not really using them myself, but I'll bet they're easy to add. Patch
41
+ me and be famous!
42
+
43
+ ## Tricks
44
+
45
+ ### Regexps
46
+
47
+ You can match arguments against regexps:
48
+
49
+ lambda do
50
+ ...
51
+ end.should run_command('convert', /.gif\z/, /.png\z/)
52
+
53
+ ### Wildcards
54
+
55
+ An integer, `n`, matches any `n` arguments:
56
+
57
+ lambda do
58
+ system 'diff', 'old.txt', 'new.txt')
59
+ end.should run_command('diff', 2)
60
+
61
+ An range matches any number of arguments in that range:
62
+
63
+ lambda do
64
+ system 'diff', '-w', 'one.txt', 'two.txt', 'three.txt'
65
+ end.should run_command('diff', '-w', 2..3)
66
+
67
+ `:*` matches any number of arguments:
68
+
69
+ lamdba do
70
+ system 'hostname'
71
+ end.should run_command('convert', :*, 'target.png')
72
+
73
+ `:+` matches at least one argument:
74
+
75
+ lamdba do
76
+ system 'hostname'
77
+ end.should run_command('gem', 'install', :+)
78
+
79
+ Any combination of wildcards can be used together.
80
+
81
+ ### Recording
82
+
83
+ You can record the commands run during a block:
84
+
85
+ commands = CommandTest.record do
86
+ system 'convert', 'bad.gif', 'good.png'
87
+ system 'identify', 'good.png'
88
+ end
89
+ commands # [['convert', 'bad.gif', 'good.png'], ['identify', 'good.png']]
90
+
91
+ And then match them yourself:
92
+
93
+ CommandTest.match?(commands.first, ['convert', :*])
94
+
95
+ You can use this to check that commands were run in a certain order, a
96
+ certain number of times, in a pretty pattern, ... the possibilities
97
+ are endless!
98
+
99
+ ## Contributing
100
+
101
+ * Bug reports: http://github.com/oggy/command_test/issues
102
+ * Source: http://github.com/oggy/command_test
103
+ * Patches: Fork on Github, send pull request.
104
+ * Ensure patch includes tests.
105
+ * Leave the version alone, or bump it in a separate commit.
106
+
107
+ ## Copyright
108
+
109
+ Copyright (c) 2010 George Ogata. See LICENSE for details.
@@ -0,0 +1,8 @@
1
+ require 'ritual'
2
+
3
+ spec_task :spec do |t|
4
+ t.pattern = 'spec/unit/**/*_spec.rb'
5
+ t.libs << 'lib' << 'spec'
6
+ end
7
+
8
+ cuke_task :cucumber
@@ -0,0 +1,60 @@
1
+ Feature: RSpec Integration
2
+
3
+ As a developer who uses RSpec
4
+ I want to use Command Test
5
+ So I can write beautiful tests
6
+
7
+ Scenario: Using run_command
8
+ Given I have a file "spec.rb" containing:
9
+ """
10
+ require 'command_test'
11
+
12
+ describe "#run_command" do
13
+ describe "when using should" do
14
+ it "should pass if the command is run" do
15
+ lambda do
16
+ system 'sh', '-c', ''
17
+ end.should run_command('sh', '-c', '')
18
+ end
19
+
20
+ it "should fail if the command is not run" do
21
+ lambda do
22
+ system 'sh', '-c', 'true'
23
+ end.should run_command('sh', '-c', '')
24
+ end
25
+ end
26
+
27
+ describe "when using should_not" do
28
+ it "should pass if the command is not run" do
29
+ lambda do
30
+ system 'sh', '-c', 'true'
31
+ end.should_not run_command('sh', '-c', '')
32
+ end
33
+
34
+ it "should fail if the command is run" do
35
+ lambda do
36
+ system 'sh', '-c', ''
37
+ end.should_not run_command('sh', '-c', '')
38
+ end
39
+ end
40
+ end
41
+ """
42
+ When I run "spec" on "spec.rb"
43
+ Then the output should contain ".F.F"
44
+ And the output should contain:
45
+ """
46
+ This command should have been run, but was not:
47
+ "sh" "-c" ""
48
+ These were the commands run:
49
+ "sh" "-c" "true"
50
+ """
51
+ And the output should contain:
52
+ """
53
+ This command should not have been run, but was:
54
+ "sh" "-c" ""
55
+ These were the commands run:
56
+ "sh" "-c" ""
57
+ """
58
+ And the output should contain in this order
59
+ | This command should have been run, but was not |
60
+ | This command should not have been run, but was |
@@ -0,0 +1,24 @@
1
+ Given /^I have a file "(.*?)" containing:$/ do |file_name, content|
2
+ path = "#{TMP}/#{file_name}"
3
+ open(path, 'w'){|f| f.print content}
4
+ end
5
+
6
+ When /^I run "(.*?)" on "(.*?)"$/ do |command, file_name|
7
+ Dir.chdir ROOT do
8
+ @output = `#{command} #{TMP}/#{file_name} 2>&1`
9
+ end
10
+ end
11
+
12
+ Then /^the output should contain "(.*?)"$/ do |fragment|
13
+ @output.should include(fragment)
14
+ end
15
+
16
+ Then /^the output should contain:$/ do |fragment|
17
+ @output.should include(fragment)
18
+ end
19
+
20
+ Then /^the output should contain in this order$/ do |table|
21
+ table.raw.inject(0) do |index, row|
22
+ index && @output.index(row.first, index)
23
+ end.should_not be_nil
24
+ end
@@ -0,0 +1,13 @@
1
+ require 'fileutils'
2
+ require 'spec/expectations'
3
+
4
+ ROOT = File.dirname(File.dirname(File.dirname(__FILE__)))
5
+ TMP = "#{ROOT}/features/tmp"
6
+
7
+ Before do
8
+ FileUtils.mkdir_p(TMP)
9
+ end
10
+
11
+ After do
12
+ FileUtils.rm_rf(TMP)
13
+ end
@@ -0,0 +1,58 @@
1
+ Feature: Test Unit Integration
2
+
3
+ As a developer who uses Test::Unit
4
+ I want to use Command Test
5
+ So I can write beautiful tests
6
+
7
+ Scenario: Using run_command
8
+ Given I have a file "test.rb" containing:
9
+ """
10
+ require 'test/unit'
11
+ require 'command_test'
12
+
13
+ class CommandTests < Test::Unit::TestCase
14
+ def test_assert_runs_command_passes_if_the_command_is_run
15
+ assert_runs_command 'sh', '-c', '' do
16
+ system 'sh', '-c', ''
17
+ end
18
+ end
19
+
20
+ def test_assert_runs_command_fails_if_the_command_is_not_run
21
+ assert_runs_command 'sh', '-c', '' do
22
+ system 'sh', '-c', 'true'
23
+ end
24
+ end
25
+
26
+ def test_assert_does_not_run_command_passes_if_the_command_is_not_run
27
+ assert_does_not_run_command 'sh', '-c', '' do
28
+ system 'sh', '-c', 'true'
29
+ end
30
+ end
31
+
32
+ def test_assert_does_not_run_command_fails_if_the_command_is_run
33
+ assert_does_not_run_command 'sh', '-c', '' do
34
+ system 'sh', '-c', ''
35
+ end
36
+ end
37
+ end
38
+ """
39
+ When I run "ruby -Ilib" on "test.rb"
40
+ # Test::Unit sorts tests alphabetically.
41
+ Then the output should contain "F.F."
42
+ And the output should contain:
43
+ """
44
+ This command should have been run, but was not:
45
+ "sh" "-c" ""
46
+ These were the commands run:
47
+ "sh" "-c" "true"
48
+ """
49
+ And the output should contain:
50
+ """
51
+ This command should not have been run, but was:
52
+ "sh" "-c" ""
53
+ These were the commands run:
54
+ "sh" "-c" ""
55
+ """
56
+ And the output should contain in this order
57
+ | This command should not have been run, but was |
58
+ | This command should have been run, but was not |
@@ -0,0 +1,70 @@
1
+ require 'shellwords'
2
+ require 'command_test/core_extensions'
3
+ require 'command_test/parser'
4
+ require 'command_test/matcher'
5
+ require 'command_test/adapters'
6
+ require 'command_test/tests'
7
+
8
+ module CommandTest
9
+ class << self
10
+ #
11
+ # Return the list of commands run during the given block.
12
+ #
13
+ # Each command is an Array of "words" (command and arguments).
14
+ #
15
+ def record
16
+ commands = []
17
+ recorders << lambda{|c| commands << c}
18
+ begin
19
+ yield
20
+ ensure
21
+ recorders.pop
22
+ end
23
+ commands
24
+ end
25
+
26
+ #
27
+ # Return true if the given +actual+ command matches the +expected+
28
+ # spec.
29
+ #
30
+ # The elements of +expected+ may be one of these:
31
+ #
32
+ # * A String in +expected+ matches the corresponding element in
33
+ # +actual+.
34
+ # * A Regexp must match the corresponding element in +actual+.
35
+ # * An Integer, n, matches the next n elements of +actual+.
36
+ # * A Range, a...b, can match the next i elements of +actual+,
37
+ # for a <= i < b.
38
+ # * :+ can match 1 or more elements in +actual+.
39
+ # * :* can match any number of elements (including zero) in
40
+ # +actual+.
41
+ #
42
+ def match?(expected, actual)
43
+ matcher.match?(expected, actual)
44
+ end
45
+
46
+ def record_command(command, *args) # :nodoc:
47
+ words = Shellwords.shellwords(command).concat(args)
48
+ recorders.each{|r| r.call(words)}
49
+ end
50
+
51
+ def record_interpreted_command(command) # :nodoc:
52
+ words = parser.parse(command)
53
+ recorders.each{|r| r.call(words)}
54
+ end
55
+
56
+ private
57
+
58
+ def recorders
59
+ Thread.current[:command_recorders] ||= []
60
+ end
61
+
62
+ def parser
63
+ @parser ||= Parser.new
64
+ end
65
+
66
+ def matcher
67
+ @matcher ||= Matcher.new
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,2 @@
1
+ require 'command_test/adapters/rspec' if Object.const_defined?(:Spec)
2
+ require 'command_test/adapters/test_unit' if Object.const_defined?(:Test) && Test.const_defined?(:Unit)
@@ -0,0 +1,41 @@
1
+ module CommandTest
2
+ module RSpec
3
+ module Matchers
4
+ #
5
+ # Matches if the proc runs the given command.
6
+ #
7
+ # lambda do
8
+ # ...
9
+ # end.should run_command('convert', 'evil.gif', 'good.png')
10
+ #
11
+ # Commands are matched according to CommandTest.match? .
12
+ #
13
+ def run_command(*command)
14
+ RunCommand.new(command)
15
+ end
16
+ end
17
+
18
+ class RunCommand
19
+ def initialize(expected)
20
+ @expected = expected
21
+ end
22
+
23
+ def matches?(proc)
24
+ @test = Tests::RunsCommand.new(@expected, &proc)
25
+ @test.matches?
26
+ end
27
+
28
+ def failure_message_for_should
29
+ @test.positive_failure_message
30
+ end
31
+
32
+ def failure_message_for_should_not
33
+ @test.negative_failure_message
34
+ end
35
+ end
36
+
37
+ ::Spec::Runner.configure do |config|
38
+ config.send :include, Matchers
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,43 @@
1
+ module CommandTest
2
+ module Adapters
3
+ module TestUnit
4
+ module Assertions
5
+ #
6
+ # Passes if the block runs the given command.
7
+ #
8
+ # assert_runs_command 'convert', 'evil.gif', 'good.png' do
9
+ # ...
10
+ # end
11
+ #
12
+ # Commands are matched according to CommandTest.match? .
13
+ #
14
+ def assert_runs_command(*expected, &block)
15
+ result = Tests::RunsCommand.new(expected, &block)
16
+ matches = result.matches?
17
+ assert_block(matches ? nil : result.positive_failure_message) do
18
+ matches
19
+ end
20
+ end
21
+
22
+ #
23
+ # Passes if the block does not run the given command.
24
+ #
25
+ # assert_does_not_run_command 'convert', 'evil.gif', 'good.png' do
26
+ # ...
27
+ # end
28
+ #
29
+ # Commands are matched according to CommandTest.match? .
30
+ #
31
+ def assert_does_not_run_command(*expected, &block)
32
+ result = Tests::RunsCommand.new(expected, &block)
33
+ matches = result.matches?
34
+ assert_block(matches ? result.negative_failure_message : nil) do
35
+ !matches
36
+ end
37
+ end
38
+ end
39
+
40
+ ::Test::Unit::TestCase.send :include, Assertions
41
+ end
42
+ end
43
+ end