atto 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,15 +1,14 @@
1
1
  INTRODUCTION
2
2
 
3
3
  Atto is an ultra-tiny self-contained testing framework inspired by
4
- and partially based on nanotest. It is self-contained in that it needs no
5
- external libraries. Every file in this project is,and will remain under 100
6
- lines long, comments included.
7
-
4
+ and partially based on nanotest by mynyml. It is self-contained in that it
5
+ needs no external libraries. Every ruby file in this project is, and will remain
6
+ under 100 lines long, comments included.
8
7
 
9
8
  USAGE
10
9
 
11
10
  To use it in your tests, for every ruby file lib/foo/bar.rb in your project,
12
- make a test file lib/foo/test_bar.rb and start it with:
11
+ make a test file lib/foo/test_bar.rb and start it with:
13
12
 
14
13
  require 'atto'
15
14
  include Atto::Test
@@ -20,8 +19,37 @@ assert "A test that will always suceed" do true end
20
19
  assert { Foo::Bar }
21
20
 
22
21
  Then run the command atto from your project directory and it will run the tests
23
- automatically, every time you change either the lib file or the test file. It
24
- will also detect new files being added.
22
+ in the test directory automatically, and then, every time you change either a
23
+ lib file or a test file, it will run the relevant test again. It will also
24
+ detect new files being added.
25
+
26
+ Since version 0.9.1, atto has a tiny command line and environment options
27
+ module, and the atto command understands the following command line options:
28
+ --help -h Display a help message.
29
+ --project=dir -pdir Sets project directory.
30
+ --lib=sub -lsub Sets project library subdirectory.
31
+ --test=sub -tsub Sets project test subdirectory.
32
+ --skip -s Skips tests on startup.
33
+
34
+ Unknown options will be completely ignored. You may also set the corresponding
35
+ environment variables ATTO_HELP, ATTO_PROJECT, ATTO_LIB, ATTO_TEST, ATTO_SKIP
36
+ for the same effect as the command line options.
37
+
38
+ Most useful here is the --skip option which allows you to skip running all tests
39
+ on startup. This is invaluable for projects that have many slow-running tests.
40
+ The help message made run.rb reach the 99 lines limit, so it looks like no new
41
+ features will be implemented in the atto command. :)
42
+
43
+ To clear out any possible misunderstandings, --project is used to set the
44
+ project directory, --test and --lib are used to specify *sub*directory names.
45
+ It is currently required that the test dir and the lib dir are subdirectories
46
+ of the project directory.
47
+
48
+ For example:
49
+
50
+ atto --project=~/src/foo --lib=libs --test=tests
51
+
52
+ Will run the tests in ~/src/foo/tests for the library files in ~/src/foo/libs.
25
53
 
26
54
  LICENSE
27
55
 
data/Rakefile CHANGED
@@ -1,11 +1,10 @@
1
- # Rakefile added by John Mair (banisterfiend)
2
-
3
- require 'rake/gempackagetask'
1
+ require 'rubygems'
2
+ require 'rubygems/package_task'
4
3
  require 'rake/clean'
5
4
  CLEAN.include("pkg/*.gem")
6
5
 
7
6
 
8
- ATTO_VERSION = "0.9.0"
7
+ ATTO_VERSION = "0.9.1"
9
8
 
10
9
  def apply_spec_defaults(s)
11
10
  end
@@ -28,7 +27,7 @@ spec = Gem::Specification.new do |s|
28
27
  s.executables = "atto"
29
28
  end
30
29
 
31
- Rake::GemPackageTask.new(spec) do |pkg|
30
+ Gem::PackageTask.new(spec) do |pkg|
32
31
  pkg.need_zip = false
33
32
  pkg.need_tar = false
34
33
  end
@@ -2,8 +2,10 @@
2
2
  module Atto
3
3
  # Ansi colors for red/green display after testing.
4
4
  autoload :Ansi, 'atto/ansi'
5
+ # Commandline and environment options
6
+ autoload :Cop , 'atto/cop'
5
7
  # Testing
6
8
  autoload :Test, 'atto/test'
7
9
  # Autorunning tests
8
10
  autoload :Run, 'atto/run'
9
- end
11
+ end
@@ -0,0 +1,88 @@
1
+ module Atto
2
+ # Cop is a module for commandline (and environment) options
3
+ module Cop
4
+
5
+ # Gets an option from the environment. The key will be uppercased, prepended
6
+ # by the uppercase basename of $0 without extension and _, and any spaces,
7
+ # dashes will be replaced by underscores. Returns the value found, or
8
+ # default if not found, and a boolean that indicates if the key was found
9
+ # or not found.
10
+ def get_environment(key, default= nil)
11
+ base = File.basename($0).gsub(/\..*\Z/,'').upcase + "_"
12
+ envkey = base + key.to_s.upcase.gsub('[ \.\-]', '_')
13
+ res = ENV[envkey]
14
+ if res
15
+ return res, true
16
+ end
17
+ return default, false
18
+ end
19
+
20
+ # Gets a command line argument from ARGV, on condition that it is not
21
+ # a --command, or preceded by a -c style option. It recognizes -- also.
22
+ def get_numarg(num, default=nil)
23
+ numkey = num.to_i
24
+ skip , aid, index = true, [], 0
25
+ while index < ARGV.size
26
+ arg = ARGV[index]
27
+ if arg == '--'
28
+ skip = false
29
+ elsif (arg[0..1] == '--') && skip
30
+ elsif arg[0] == '-' && skip
31
+ else
32
+ aid << arg
33
+ end
34
+ index += 1
35
+ end
36
+ return aid[num], true if aid[num]
37
+ return default, false
38
+ end
39
+
40
+ # Gets a long --foo=bar style commandline argument from ARGV. The key will
41
+ # be lowercased, prepended with -- and any spaces, periods or underscores
42
+ # will be replaced by dashes. Returns the value found, or default if not
43
+ # found, and a boolean that indicates if the key was found or not found.
44
+ def get_argument(key, default=nil)
45
+ argkey = "--" + key.to_s.downcase.gsub('[ \.\_]', '-')
46
+ res = ARGV.reverse.find{ |arg| arg =~ /\A#{argkey}(\Z|=)/ }
47
+ return default, false unless res
48
+ index = res.index('=')
49
+ return true, true unless index
50
+ return res[index + 1, res.size] , true
51
+ end
52
+
53
+ # Gets a long -cbar style commandline argument from ARGV. The first
54
+ # character of key will be taken, lowercased, and prepended with -
55
+ # Returns the value found, or default if not found, and
56
+ # a boolean that indicates if the key was found or not found.
57
+ def get_arg(key, default=nil)
58
+ argkey = "-" + key.to_s[0].downcase
59
+ res = ARGV.reverse.find{ |arg| arg =~ /\A#{argkey}/ }
60
+ return default, false unless res
61
+ if res.size == 2
62
+ return true, true
63
+ end
64
+ return res[2, res.size] , true
65
+ end
66
+
67
+ def get(key, default=nil)
68
+ if key.respond_to?(:to_int)
69
+ res, found = get_numarg(key, default)
70
+ return res if found
71
+ end
72
+ res, found = get_argument(key, default)
73
+ return res if found
74
+ res, found = get_arg(key, default)
75
+ return res if found
76
+ res, found = get_environment(key, default)
77
+ return res if found
78
+ return default
79
+ end
80
+
81
+ def [](key)
82
+ return get(key, nil)
83
+ end
84
+
85
+ extend self
86
+ end
87
+ end
88
+
@@ -0,0 +1,64 @@
1
+ module Atto
2
+ # A module for handling command line options
3
+ module Opt
4
+
5
+ # Gets an argument in the long form
6
+ def self.getargument(key, default=nil)
7
+ keyarg = key.to_s.downcase.gsub(/[_ ]/, '-')
8
+ arg = ARGS.select{ |f| f =~ /\A--#{keyarg}(\Z|\=)/ }.last
9
+ return default, false unless arg
10
+ ind = arg.index('=')
11
+ if ind
12
+ res = arg[ind + 1, arg.size]
13
+ return res, true unless res.empty?
14
+ return default, true
15
+ end
16
+ return true, true
17
+ end
18
+
19
+ # Gets an argument in the short form
20
+ def self.getarg(key, default = nil)
21
+ shortarg = key.to_s[0]
22
+ arg = ARGS.index{ |f| f =~ /\A-#{shortarg}\Z)/ }.last
23
+ return default, false unless arg
24
+ return ARGS[arg+1] || default, true
25
+ end
26
+
27
+ # Gets an environment variable
28
+ def self.getenv
29
+ envarg = key.to_s.upcase.gsub(/[ \-]/, '_')
30
+ env = ENV[envarg]
31
+ return default, false unless env
32
+ return env || default, true
33
+ end
34
+
35
+ # Gets an option from arguments or from the environment (in that order)
36
+ def self.get(key, default = nil)
37
+ keyarg = key.to_s.downcase.gsub(/[_ ]/, '-')
38
+ arg = ARGS.select{ |f| f =~ /\A--#{keyarg}(\Z|\=)/ }.last
39
+ if arg
40
+ ind = arg.index('=')
41
+ if ind
42
+ res = arg[ind + 1, arg.size]
43
+ return res unless res.empty?
44
+ return default
45
+ else
46
+ return default || true
47
+ end
48
+ end
49
+ # Short arguments
50
+ shortarg = key.to_s[0]
51
+ arg = ARGS.index{ |f| f =~ /\A-#{shortarg}\Z)/ }.last
52
+
53
+
54
+ envarg = key.to_s.upcase.gsub(/[ \-]/, '_')
55
+ env = ENV[envarg]
56
+ return env || default
57
+ end
58
+
59
+ def [](key)
60
+ return self.get(key)
61
+ end
62
+
63
+ end
64
+ end
@@ -7,16 +7,8 @@ module Atto
7
7
  end
8
8
 
9
9
  # Find all Ruby all files under the named dir
10
- def all_files(name)
11
- return Dir.new(name).inject([]) do |res, e|
12
- full = File.join(name, e)
13
- if Dir.exist?(full) && e !='.' && e != '..'
14
- res += all_files(full)
15
- else
16
- res << full if full =~ /\.rb\Z/
17
- end
18
- res
19
- end
10
+ def all_ruby_files(name)
11
+ Dir["#{name}/**/*.rb"]
20
12
  end
21
13
 
22
14
  # updates the timestamp info for files
@@ -28,7 +20,7 @@ module Atto
28
20
  end
29
21
  end
30
22
 
31
- # matches libfiles wih testfiles
23
+ # matches libfiles with testfiles
32
24
  def match_files(libfiles, testfiles)
33
25
  return libfiles.inject({}) do |res, libname|
34
26
  testname = libname.dup
@@ -41,11 +33,13 @@ module Atto
41
33
  end
42
34
 
43
35
  # Runs a list of tests
44
- def run_tests(list)
36
+ def run_tests(list, skip = false)
45
37
  return list.inject({}) do |results, file|
46
- puts("Running tests for #{file}:")
47
- res = system("ruby -I #@libdir -I #@testdir #{file}")
48
- puts res ? "OK!" : "Failed!"
38
+ puts(skip ? "Skipping #{file}..." : "Running tests for #{file}:")
39
+ unless skip
40
+ res = system("ruby -I #@libdir -I #@testdir #{file}")
41
+ puts res ? "OK!" : "Failed!"
42
+ end
49
43
  results[file] = Time.now
50
44
  results
51
45
  end
@@ -56,22 +50,34 @@ module Atto
56
50
  ran_tests[k] ? ran_tests[k] <= v.mtime : true
57
51
  end
58
52
 
59
- # updates all state info
53
+ # Updates all state info
60
54
  def update_all
61
- @libfiles = all_files(@libdir)
62
- @testfiles = all_files(@testdir)
55
+ @libfiles = all_ruby_files(@libdir)
56
+ @testfiles = all_ruby_files(@testdir)
63
57
  @matchfiles= match_files(@libfiles, @testfiles)
64
58
  @libinfo = update_info(@libfiles)
65
59
  @testinfo = update_info(@testfiles)
66
60
  end
67
61
 
62
+ # Shows help message
63
+ def help
64
+ warn "Usage: #{$0} OPTIONS.\nRuns unit tests in the current directory.\n"
65
+ warn " --help -h Display this help message."
66
+ warn " --project=dir -pdir Sets project directory."
67
+ warn " --lib=sub -lsub Sets project library subdirectory."
68
+ warn " --test=sub -tsub Sets project test subdirectory."
69
+ warn " --skip -s Skips tests on startup.\n"
70
+ return 0
71
+ end
72
+
68
73
  # Main, runs the tests when needed
69
74
  def main
70
- @projdir = ARGV[0] || Dir.pwd
71
- @libdir = File.join(@projdir, ARGV[1] || 'lib')
72
- @testdir = File.join(@projdir, ARGV[2] || 'test')
75
+ return help if Atto::Cop.get(:help)
76
+ @projdir = Atto::Cop.get(:project, Dir.pwd)
77
+ @libdir = File.join(@projdir, Atto::Cop.get(:lib, 'lib'))
78
+ @testdir = File.join(@projdir, Atto::Cop.get(:test, 'test'))
73
79
  update_all
74
- @ran_tests = run_tests(@testfiles)
80
+ @ran_tests = run_tests(@testfiles, Atto::Cop.get(:skip, false))
75
81
  loop do
76
82
  update_all
77
83
  torun = @testinfo.select do |k,v|
@@ -43,7 +43,7 @@ module Atto
43
43
  begin
44
44
  Timeout.timeout(delay) do res = block.call ; end
45
45
  rescue
46
- raised = $!
46
+ raised = $!.dup
47
47
  end
48
48
  return res, raised
49
49
  end
@@ -0,0 +1,99 @@
1
+ require 'atto/test'
2
+ include Atto::Test
3
+ require 'atto'
4
+
5
+ assert "Cop is defined" do
6
+ Atto::Cop
7
+ end
8
+
9
+ # Set up some fake environent and argument options
10
+ p $0
11
+ ENV['TEST_COP_FOO'] = 'bar'
12
+ ENV['TEST_COP_BAZ'] = ""
13
+ ARGV << '--foo=quux'
14
+ ARGV << 'file1'
15
+ ARGV << '--foo=bar'
16
+ ARGV << '-fquux'
17
+ ARGV << '-fbaz'
18
+ ARGV << '--bar'
19
+ ARGV << '-b'
20
+ ARGV << 'file2'
21
+ ARGV << '--'
22
+ ARGV << '--file3'
23
+
24
+
25
+ assert "Cop is defined" do
26
+ Atto::Cop
27
+ end
28
+
29
+ assert "Getting options from environment works" do
30
+ res, found = Atto::Cop.get_environment(:baz)
31
+ found
32
+ end
33
+
34
+ assert "Getting options from environment works" do
35
+ res, found = Atto::Cop.get_environment(:foo)
36
+ found && res == 'bar'
37
+ end
38
+
39
+ assert "Getting long command line arguments works" do
40
+ res, found = Atto::Cop.get_argument(:foo)
41
+ found && res == 'bar'
42
+ end
43
+
44
+ assert "Getting short command line arguments works" do
45
+ res, found = Atto::Cop.get_arg(:foo)
46
+ found && res == 'baz'
47
+ end
48
+
49
+ assert "Indexed command line file arguments works" do
50
+ res, found = Atto::Cop.get_numarg(0)
51
+ found && res == 'file1'
52
+ end
53
+
54
+ assert "Indexed command line file arguments works" do
55
+ res, found = Atto::Cop.get_numarg(1)
56
+ found && res == 'file2'
57
+ end
58
+
59
+ assert "Indexed command line file arguments works" do
60
+ res, found = Atto::Cop.get_numarg(2)
61
+ found && res == '--file3'
62
+ end
63
+
64
+ assert "Indexed command line file arguments works" do
65
+ res, found = Atto::Cop.get_numarg(3)
66
+ (!found) && res.nil?
67
+ end
68
+
69
+
70
+ assert "Getting generic command line arguments works" do
71
+ res = Atto::Cop.get(2)
72
+ res == '--file3'
73
+ end
74
+
75
+ assert "Getting generic command line arguments works" do
76
+ res = Atto::Cop.get(1)
77
+ res == 'file2'
78
+ end
79
+
80
+ assert "Getting generic command line arguments works" do
81
+ res = Atto::Cop.get(0)
82
+ res == 'file1'
83
+ end
84
+
85
+ assert "Getting generic command line arguments works" do
86
+ res = Atto::Cop.get(:foo)
87
+ res == 'bar'
88
+ end
89
+
90
+ assert "Getting generic command line arguments works" do
91
+ res = Atto::Cop.get(:bar)
92
+ res == true
93
+ end
94
+
95
+ assert "Defaults work" do
96
+ Atto::Cop.get(:kazz, 'default') == 'default'
97
+ end
98
+
99
+ # We end here before the 100 line limit! :)
@@ -1,10 +1,10 @@
1
1
  require 'atto'
2
2
  include Atto::Test
3
3
 
4
- assert "Atto is defined" do Atto end
4
+ assert "Atto is defined" do Atto end
5
5
  assert "Atto::Test is defined" do Atto::Test end
6
6
  assert "Success can be detected" do true end
7
- assert "Works with nexted asserts" do
7
+ assert "Works with nested asserts" do
8
8
  assert "This is a nested assert" do true end
9
9
  end
10
10
 
@@ -20,3 +20,5 @@ assert "Atto::Test#describe_tests is defined" do Atto::Test.describe_tests end
20
20
 
21
21
 
22
22
 
23
+
24
+
metadata CHANGED
@@ -1,73 +1,58 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: atto
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 9
8
- - 0
9
- version: 0.9.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Beoran
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-05-07 00:00:00 +02:00
18
- default_executable:
12
+ date: 2011-06-16 00:00:00.000000000Z
19
13
  dependencies: []
20
-
21
- description: "An ultra-tiny self-contained testing framework. "
14
+ description: ! 'An ultra-tiny self-contained testing framework. '
22
15
  email: beoran@rubyforge.org
23
- executables:
16
+ executables:
24
17
  - atto
25
18
  extensions: []
26
-
27
19
  extra_rdoc_files: []
28
-
29
- files:
20
+ files:
30
21
  - Rakefile
31
22
  - README
32
23
  - lib/atto.rb
33
24
  - lib/atto/ansi.rb
34
25
  - lib/atto/run.rb
26
+ - lib/atto/cop.rb
35
27
  - lib/atto/test.rb
28
+ - lib/atto/opt.rb
36
29
  - test/test_atto.rb
30
+ - test/atto/test_cop.rb
37
31
  - test/atto/test_ansi.rb
38
32
  - test/atto/test_test.rb
39
33
  - bin/atto
40
- has_rdoc: true
41
34
  homepage: https://github.com/beoran/atto
42
35
  licenses: []
43
-
44
36
  post_install_message:
45
37
  rdoc_options: []
46
-
47
- require_paths:
38
+ require_paths:
48
39
  - lib
49
- required_ruby_version: !ruby/object:Gem::Requirement
40
+ required_ruby_version: !ruby/object:Gem::Requirement
50
41
  none: false
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- segments:
55
- - 0
56
- version: "0"
57
- required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
47
  none: false
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- segments:
63
- - 0
64
- version: "0"
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
65
52
  requirements: []
66
-
67
53
  rubyforge_project:
68
- rubygems_version: 1.3.7
54
+ rubygems_version: 1.8.5
69
55
  signing_key:
70
56
  specification_version: 3
71
57
  summary: An ultra-tiny self-contained testing framework.
72
58
  test_files: []
73
-