cutest 1.0.0.beta → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,12 +6,9 @@ Forking tests.
6
6
  Description
7
7
  -----------
8
8
 
9
- Run tests in separate processes to avoid shared state.
10
-
11
- Each test file is run in a forked process and. Once a failure is found in a
12
- file, you get a debugger and the ability to fix the error in place. If you
13
- choose to quit the debugger, the rest of the file is skipped. This way, doing
14
- TDD is easier and running your test suite feels faster.
9
+ Each test file is run in a forked process to avoid shared state. Once a failure
10
+ is found, you get a report detailing what failed and how to locate the error
11
+ and the rest of the file is skipped.
15
12
 
16
13
  You can use the `scope` command around tests: it guarantees that no instance
17
14
  variables are shared between tests.
@@ -35,12 +32,11 @@ block as a parameter to the `test` blocks.
35
32
  The `test` method executes the passed block after running `prepare` and
36
33
  `setup`. This is where assertions must be declared.
37
34
 
38
- Two assertions are available: `assert` and `assert_raise`. The first accepts a
39
- value and raises an `AssertionFailed` exception if it's false or nil, and the
40
- later receives an expected exception and a block: the block is executed and
41
- the raised exception is compared with the expected one. An `AssertionFailed`
42
- exception is raised if the block runs fine or if the raised exception doesn't
43
- match the expectation.
35
+ Three assertions are available: `assert`, that accepts a value and raises
36
+ if it's false or nil; `assert_equal`, that raises if its arguments are not
37
+ equal; and `assert_raise`, that executes a passed block and compares the raised
38
+ exception to the expected one. In all cases, if the expectation is no met, an
39
+ `AssertionFailed` exception is raised.
44
40
 
45
41
  Usage
46
42
  -----
@@ -115,24 +111,23 @@ running them.
115
111
  Handling errors
116
112
  ---------------
117
113
 
118
- If you get an error when running the tests, you will see a debugger prompt:
119
-
120
- Exception: Cutest::AssertionFailed
121
- Type continue to retry or edit to modify the source
122
- .Breakpoint 1 at test/setup.rb:14
123
- [12, 16] in test/setup.rb
124
- 12
125
- 13 test "should preserve the original values from the setup" do |params|
126
- => 14 assert 24 == params[:a]
127
- 15 end
128
- 16
129
- test/setup.rb:14
130
- assert 24 == params[:a]
131
- (rdb:1)
132
-
133
- Instead of a getting a report of the error, you get to interact with it live
134
- and even fix it: if you type `edit`, the file is opened in your editor. Once
135
- you fix the code and save it, the debugger will reload it and retry.
114
+ If you get an error when running the tests, this is what you will see:
115
+
116
+ Exception: assert_equal 24, params[:a] # 24 != 23
117
+ test/setup.rb +14
118
+
119
+ Command Line Interface
120
+ ----------------------
121
+
122
+ The tool `cutest` accepts a list of files and sends them to `Cutest.run`. If
123
+ you need to require a file or library before running the tests, as is the case
124
+ with test helpers, use the `-r` flag:
125
+
126
+ $ cutest -r test/helper.rb test/*_test.rb
127
+
128
+ If you want to check which version you are running, try the `-v` flag.
129
+
130
+ If you want to require ruby-debug, use the `--debug` flag.
136
131
 
137
132
  Installation
138
133
  ------------
data/bin/cutest CHANGED
@@ -3,7 +3,7 @@
3
3
  require File.expand_path("../lib/cutest", File.dirname(__FILE__))
4
4
 
5
5
  if ARGV.empty?
6
- puts "usage: cutest [-r lib] [-v] file ..."
6
+ puts "usage: cutest [-r lib] [-v] [--debug] file ..."
7
7
  exit
8
8
  end
9
9
 
@@ -13,7 +13,7 @@ class Cutest
13
13
  # http://github.com/soveran/clap
14
14
  # http://rubygems.org/gems/clap
15
15
  class Clap
16
- VERSION = "0.0.1"
16
+ VERSION = "0.0.2"
17
17
 
18
18
  attr :argv
19
19
  attr :opts
@@ -23,7 +23,7 @@ class Cutest
23
23
  end
24
24
 
25
25
  def initialize(argv, opts)
26
- @argv = argv.reverse.dup
26
+ @argv = argv.dup
27
27
  @opts = opts
28
28
  end
29
29
 
@@ -31,13 +31,24 @@ class Cutest
31
31
  args = []
32
32
 
33
33
  while argv.any?
34
- item = argv.pop
35
34
 
36
- if opts[item]
35
+ item = argv.shift
36
+ flag = opts[item]
37
+
38
+ if flag
39
+
40
+ # Work around lambda semantics in 1.8.7.
41
+ arity = [flag.arity, 0].max
42
+
43
+ # Raise if there are not enough parameters
44
+ # available for the flag.
45
+ if argv.size < arity
46
+ raise ArgumentError
47
+ end
37
48
 
38
49
  # Call the lambda with N items from argv,
39
50
  # where N is the lambda's arity.
40
- opts[item].call(*argv.pop(opts[item].arity))
51
+ flag.call(*argv.shift(arity))
41
52
  else
42
53
 
43
54
  # Collect the items that don't correspond to
@@ -52,7 +63,8 @@ class Cutest
52
63
  end
53
64
 
54
65
  files = Cutest::Clap.run ARGV,
55
- "-r" => lambda { |file| require file },
56
- "-v" => lambda { puts Cutest::VERSION }
66
+ "-r" => lambda { |file| require file },
67
+ "-v" => lambda { puts Cutest::VERSION },
68
+ "--debug" => lambda { ENV["DEBUG"] = true }
57
69
 
58
70
  Cutest.run(Dir[*files]) if files.any?
@@ -1,11 +1,11 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cutest"
3
- s.version = "1.0.0.beta"
3
+ s.version = "1.0.0.beta1"
4
4
  s.summary = "Forking tests."
5
5
  s.description = "Run tests in separate processes to avoid shared state."
6
6
  s.authors = ["Damian Janowski", "Michel Martens"]
7
7
  s.email = ["djanowski@dimaion.com", "michel@soveran.com"]
8
8
  s.homepage = "http://github.com/djanowski/cutest"
9
- s.files = ["LICENSE", "README.markdown", "Rakefile", "lib/cutest.rb", "cutest.gemspec", "test/assert.rb", "test/assert_raise.rb", "test/prepare.rb", "test/run.rb", "test/scopes.rb", "test/setup.rb"]
9
+ s.files = ["LICENSE", "README.markdown", "Rakefile", "lib/cutest.rb", "cutest.gemspec", "test/assert.rb", "test/assert_equal.rb", "test/assert_raise.rb", "test/prepare.rb", "test/run.rb", "test/scopes.rb", "test/setup.rb"]
10
10
  s.executables.push "cutest"
11
11
  end
@@ -1,59 +1,56 @@
1
- begin
2
- require "ruby-debug"
3
- rescue LoadError
4
- puts "Cutest needs ruby-debug, but it couldn't be required."
5
- puts "Please install ruby-debug or ruby-debug19 and try again."
6
- exit
7
- end
1
+ class Cutest
2
+ VERSION = "1.0.0.beta1"
8
3
 
9
- Debugger.settings[:autoeval] = 1
10
- Debugger.settings[:autolist] = 1
11
- Debugger.settings[:listsize] = 5
12
- Debugger.settings[:reload_source_on_change] = 1
4
+ if ENV["DEBUG"]
5
+ begin
6
+ require "ruby-debug"
7
+ rescue LoadError
8
+ puts "Cutest needs ruby-debug, but it couldn't be required."
9
+ puts "Please install ruby-debug or ruby-debug19 and try again."
10
+ exit
11
+ end
13
12
 
14
- class Cutest
15
- VERSION = "1.0.0.beta"
13
+ Debugger.settings[:autoeval] = 1
14
+ Debugger.settings[:autolist] = 1
15
+ Debugger.settings[:listsize] = 5
16
+ Debugger.settings[:reload_source_on_change] = 1
17
+ end
16
18
 
17
19
  def self.run(files)
18
- trap("INT") { exit }
19
- trap("TERM") { exit }
20
-
21
20
  files.each do |file|
22
- Debugger.start do
21
+ stdin, stdout = IO.pipe
23
22
 
24
- loop do
25
- stdin, stdout = IO.pipe
23
+ fork do
24
+ stdin.close
26
25
 
27
- fork do
28
- stdin.close
26
+ begin
27
+ load(file)
29
28
 
30
- begin
31
- load(file)
29
+ rescue LoadError, SyntaxError
30
+ puts ["\n", error([file, $!.message])]
31
+ exit
32
32
 
33
- rescue LoadError, SyntaxError
34
- puts ["\n", error([file, $!.message])]
35
- exit
33
+ rescue Exception
34
+ fn, ln = $!.backtrace.first.split(":")
35
+ message = File.readlines(fn)[ln.to_i - 1]
36
+ stdout.write("#{fn}\n#{ln}\n#{error(message.strip)} # #{$!.message}")
37
+ end
36
38
 
37
- rescue Exception
38
- fn, ln = $!.backtrace.first.split(":")
39
- stdout.write("#{fn}\n#{ln}\n#{error($!)}\n#{hint}")
40
- end
41
- end
39
+ stdout.close
40
+ end
42
41
 
43
- stdout.close
42
+ stdout.close
44
43
 
45
- Process.wait
44
+ Process.wait
46
45
 
47
- output = stdin.read
46
+ output = stdin.read
48
47
 
49
- unless output.empty?
50
- fn, ln, error, hint = output.split("\n")
51
- Debugger.add_breakpoint(fn, ln.to_i)
52
- puts ["\n", error, hint]
53
- else
54
- break
55
- end
56
- end
48
+ stdin.close
49
+
50
+ unless output.empty?
51
+ fn, ln, error = output.split("\n")
52
+
53
+ puts "\n#{error}\n#{fn} +#{ln}"
57
54
  end
58
55
  end
59
56
 
@@ -64,11 +61,6 @@ class Cutest
64
61
  "\033[01;36mException: \033[01;33m#{e}\033[00m"
65
62
  end
66
63
 
67
- def self.hint
68
- "\033[01;36mType \033[0;33mcontinue\033[0;36m to retry " +
69
- "or \033[0;33medit\033[0;36m to modify the source\033[00m"
70
- end
71
-
72
64
  class AssertionFailed < StandardError
73
65
  end
74
66
 
@@ -86,8 +78,8 @@ end
86
78
  module Kernel
87
79
  private
88
80
 
89
- # Use Thread.current[:cutest] to store information about test preparation and
90
- # setup.
81
+ # Use Thread.current[:cutest] to store information about test preparation
82
+ # and setup.
91
83
  Thread.current[:cutest] ||= { :prepare => [] }
92
84
 
93
85
  # Shortcut to access Thread.current[:cutest].
@@ -101,31 +93,31 @@ private
101
93
  Cutest::Scope.new(&block).call
102
94
  end
103
95
 
104
- # Prepare the environment in order to run the tests. This method can be called
105
- # many times, and each new block is appended to a list of preparation blocks.
106
- # When a test is executed, all the preparation blocks are ran in the order they
107
- # were declared. If called without a block, it returns the array of preparation
108
- # blocks.
96
+ # Prepare the environment in order to run the tests. This method can be
97
+ # called many times, and each new block is appended to a list of
98
+ # preparation blocks. When a test is executed, all the preparation blocks
99
+ # are ran in the order they were declared. If called without a block, it
100
+ # returns the array of preparation blocks.
109
101
  def prepare(&block)
110
102
  cutest[:prepare] << block if block_given?
111
103
  cutest[:prepare]
112
104
  end
113
105
 
114
- # Setup parameters for the tests. The block passed to setup is evaluated before
115
- # running each test, and the result of the setup block is passed to the test as
116
- # a parameter. If the setup and the tests are declared at the same level (in
117
- # the global scope or in a sub scope), it is possible to use instance
118
- # variables, but the parameter passing pattern is recommended to ensure there
119
- # are no side effects.
106
+ # Setup parameters for the tests. The block passed to setup is evaluated
107
+ # before running each test, and the result of the setup block is passed to
108
+ # the test as a parameter. If the setup and the tests are declared at the
109
+ # same level (in the global scope or in a sub scope), it is possible to use
110
+ # instance variables, but the parameter passing pattern is recommended to
111
+ # ensure there are no side effects.
120
112
  #
121
113
  # If the setup blocks are declared in the global scope and the tests are
122
114
  # declared in sub scopes, the parameter passing usage is required.
123
115
  #
124
- # Setup blocks can be defined many times, but each new definition overrides the
125
- # previous one. It is recommended to split the tests in many different files
126
- # (the report is per file, not per assertion). Usually one setup block per file
127
- # is enough, but nothing forbids having different scopes with different setup
128
- # blocks.
116
+ # Setup blocks can be defined many times, but each new definition overrides
117
+ # the previous one. It is recommended to split the tests in many different
118
+ # files (the report is per file, not per assertion). Usually one setup
119
+ # block per file is enough, but nothing forbids having different scopes
120
+ # with different setup blocks.
129
121
  def setup(&block)
130
122
  cutest[:setup] = block if block_given?
131
123
  cutest[:setup]
@@ -136,8 +128,8 @@ private
136
128
 
137
129
  # Call the prepare and setup blocks before executing the test. Even
138
130
  # though the assertions can live anywhere (it's not mandatory to put them
139
- # inside test blocks), it is necessary to wrap them in test blocks in order to
140
- # execute preparation and setup blocks.
131
+ # inside test blocks), it is necessary to wrap them in test blocks in order
132
+ # to execute preparation and setup blocks.
141
133
  def test(name = nil, &block)
142
134
  cutest[:test] = name
143
135
 
@@ -147,7 +139,13 @@ private
147
139
 
148
140
  # Assert that value is not nil or false.
149
141
  def assert(value)
150
- flunk unless value
142
+ flunk("assertion failed") unless value
143
+ print "."
144
+ end
145
+
146
+ # Assert that two values are equal.
147
+ def assert_equal(value, other)
148
+ flunk("#{value} != #{other}") unless value == other
151
149
  print "."
152
150
  end
153
151
 
@@ -157,15 +155,15 @@ private
157
155
  yield
158
156
  rescue => exception
159
157
  ensure
160
- flunk unless exception.kind_of?(expected)
158
+ flunk("got #{exception} instead") unless exception.kind_of?(expected)
161
159
  print "."
162
160
  end
163
161
  end
164
162
 
165
163
  # Stop the tests and raise an error where the message is the last line
166
164
  # executed before flunking.
167
- def flunk
168
- exception = Cutest::AssertionFailed.new
165
+ def flunk(message = nil)
166
+ exception = Cutest::AssertionFailed.new(message)
169
167
  exception.set_backtrace([caller[1]])
170
168
 
171
169
  raise exception
@@ -0,0 +1,9 @@
1
+ test do
2
+ assert_equal 1, 1
3
+ end
4
+
5
+ test "raises if the assertion fails" do
6
+ assert_raise(Cutest::AssertionFailed) do
7
+ assert_equal 1, 2
8
+ end
9
+ end
@@ -11,7 +11,7 @@ test "if the params are modified..." do |params|
11
11
  end
12
12
 
13
13
  test "...it should preserve the original values from the setup" do |params|
14
- assert 23 == params[:a]
14
+ assert_equal 23, params[:a]
15
15
  end
16
16
 
17
17
  setup do
metadata CHANGED
@@ -6,8 +6,8 @@ version: !ruby/object:Gem::Version
6
6
  - 1
7
7
  - 0
8
8
  - 0
9
- - beta
10
- version: 1.0.0.beta
9
+ - beta1
10
+ version: 1.0.0.beta1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Damian Janowski
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-10-10 00:00:00 -03:00
19
+ date: 2010-10-30 00:00:00 -03:00
20
20
  default_executable:
21
21
  dependencies: []
22
22
 
@@ -37,6 +37,7 @@ files:
37
37
  - lib/cutest.rb
38
38
  - cutest.gemspec
39
39
  - test/assert.rb
40
+ - test/assert_equal.rb
40
41
  - test/assert_raise.rb
41
42
  - test/prepare.rb
42
43
  - test/run.rb