atto 0.9.0 → 0.9.1

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.
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
-