atto 0.9.0

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 ADDED
@@ -0,0 +1,50 @@
1
+ INTRODUCTION
2
+
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
+
8
+
9
+ USAGE
10
+
11
+ 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:
13
+
14
+ require 'atto'
15
+ include Atto::Test
16
+
17
+ # Then you can add tests like this:
18
+ assert "A test that will always suceed" do true end
19
+ # Or like this :
20
+ assert { Foo::Bar }
21
+
22
+ 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.
25
+
26
+ LICENSE
27
+
28
+ The MIT License
29
+
30
+ Copyright (c) 2011 Beoran (beoran@rubyforge.org)
31
+
32
+ Permission is hereby granted, free of charge, to any person obtaining a copy
33
+ of this software and associated documentation files (the "Software"), to deal
34
+ in the Software without restriction, including without limitation the rights
35
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36
+ copies of the Software, and to permit persons to whom the Software is
37
+ furnished to do so, subject to the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be included in
40
+ all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
48
+ THE SOFTWARE.
49
+
50
+
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ # Rakefile added by John Mair (banisterfiend)
2
+
3
+ require 'rake/gempackagetask'
4
+ require 'rake/clean'
5
+ CLEAN.include("pkg/*.gem")
6
+
7
+
8
+ ATTO_VERSION = "0.9.0"
9
+
10
+ def apply_spec_defaults(s)
11
+ end
12
+
13
+ spec = Gem::Specification.new do |s|
14
+ s.name = "atto"
15
+ s.summary = "An ultra-tiny self-contained testing framework."
16
+ s.description = s.summary + " "
17
+ s.version = ATTO_VERSION
18
+ s.author = "Beoran"
19
+ s.email = 'beoran@rubyforge.org'
20
+ s.date = Time.now.strftime '%Y-%m-%d'
21
+ s.require_path = 'lib'
22
+ s.homepage = "https://github.com/beoran/atto"
23
+ # s.platform = Gem::Platform::CURRENT
24
+ s.files = ["Rakefile" , "README" ] +
25
+ FileList["lib/atto.rb", "lib/atto/*.rb",
26
+ "test/*.rb" , "test/atto/*.rb" ].to_a
27
+ s.bindir = "bin"
28
+ s.executables = "atto"
29
+ end
30
+
31
+ Rake::GemPackageTask.new(spec) do |pkg|
32
+ pkg.need_zip = false
33
+ pkg.need_tar = false
34
+ end
35
+
36
+
37
+ task :test do
38
+ for file in FileList["test/*.rb" , "test/atto/*.rb" ] do
39
+ puts("Running tests for #{file}:")
40
+ res = system("ruby -I lib #{file}")
41
+ puts res ? "OK!" : "Failed!"
42
+ end
43
+ end
44
+
45
+ task :default => :test
46
+
data/bin/atto ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'atto'
4
+
5
+ Atto::Run.main
data/lib/atto/ansi.rb ADDED
@@ -0,0 +1,40 @@
1
+ module Atto
2
+ # ANSI colors
3
+ module Ansi
4
+ extend self
5
+
6
+ ATTRIBUTES = {
7
+ :reset => 0 , :bold => 1 , :dark => 2 , :underline => 4 ,
8
+ :blink => 5 , :negative => 7 , :concealed => 8 , :black => 30,
9
+ :red => 31, :green => 32, :yellow => 33, :blue => 34,
10
+ :magenta => 35, :cyan => 36, :white => 37, :on_black => 40,
11
+ :on_red => 41, :on_green => 42, :on_yellow => 43, :on_blue => 44,
12
+ :on_magenta=> 45, :on_cyan => 46, :on_white => 47, }
13
+
14
+ # Replaces symbols witch refer to ANSI escape codes with those escape codes.
15
+ def color(*args)
16
+ out = []
17
+ for arg in args
18
+ col = ATTRIBUTES[arg]
19
+ if col
20
+ out << "\e[#{col}m"
21
+ else
22
+ out << arg
23
+ end
24
+ end
25
+ out << "\e[0m"
26
+ return out
27
+ end
28
+
29
+ # Replaces ansi codes and returns the joined string
30
+ def color_string(*args)
31
+ return color(*args).map { |e| e.to_s }.join
32
+ end
33
+
34
+ # puts output colored with ANSI escape codes
35
+ def puts(*args)
36
+ Kernel.puts(*self.color(*args))
37
+ end
38
+
39
+ end
40
+ end
data/lib/atto/run.rb ADDED
@@ -0,0 +1,93 @@
1
+ module Atto
2
+ # Test autorunner
3
+ class Run
4
+ # Shortcut to run main
5
+ def self.main
6
+ return self.new.main
7
+ end
8
+
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
20
+ end
21
+
22
+ # updates the timestamp info for files
23
+ def update_info(files)
24
+ return files.inject({}) do |res, name|
25
+ stat = File.stat(name)
26
+ res[name] = Struct.new(:mtime).new(stat.mtime)
27
+ res
28
+ end
29
+ end
30
+
31
+ # matches libfiles wih testfiles
32
+ def match_files(libfiles, testfiles)
33
+ return libfiles.inject({}) do |res, libname|
34
+ testname = libname.dup
35
+ where = libname.rindex(File::Separator)
36
+ testname[where]= File::Separator + 'test_'
37
+ testname[File.join('','lib','')] = File.join('','test','')
38
+ res[libname] = testname if testfiles.member?(testname)
39
+ res
40
+ end
41
+ end
42
+
43
+ # Runs a list of tests
44
+ def run_tests(list)
45
+ 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!"
49
+ results[file] = Time.now
50
+ results
51
+ end
52
+ end
53
+
54
+ # Checks if a test file must run
55
+ def must_run(ran_tests, k, v)
56
+ ran_tests[k] ? ran_tests[k] <= v.mtime : true
57
+ end
58
+
59
+ # updates all state info
60
+ def update_all
61
+ @libfiles = all_files(@libdir)
62
+ @testfiles = all_files(@testdir)
63
+ @matchfiles= match_files(@libfiles, @testfiles)
64
+ @libinfo = update_info(@libfiles)
65
+ @testinfo = update_info(@testfiles)
66
+ end
67
+
68
+ # Main, runs the tests when needed
69
+ def main
70
+ @projdir = ARGV[0] || Dir.pwd
71
+ @libdir = File.join(@projdir, ARGV[1] || 'lib')
72
+ @testdir = File.join(@projdir, ARGV[2] || 'test')
73
+ update_all
74
+ @ran_tests = run_tests(@testfiles)
75
+ loop do
76
+ update_all
77
+ torun = @testinfo.select do |k,v|
78
+ must_run(@ran_tests, k, v)
79
+ end
80
+ extra = @libinfo.select do |k,v|
81
+ linked = @matchfiles[k]
82
+ linked ? must_run(@ran_tests, linked, v) : false
83
+ end.map { |k,v| @matchfiles[k] }
84
+ run_tests(torun.keys + extra).each { |k,v| @ran_tests[k] = v }
85
+ sleep(1)
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ if __FILE__ == $0
92
+ Atto::Run.main
93
+ end
data/lib/atto/test.rb ADDED
@@ -0,0 +1,80 @@
1
+ require 'timeout'
2
+
3
+ module Atto
4
+ # Tiny module for test driven development. Use with include Atto::Test.
5
+ module Test
6
+ extend self
7
+ @@failures, @@dots, @@messages = [], [], []
8
+
9
+ # Returns the file and line of the calling context
10
+ def parse_stack(stack=caller)
11
+ return *(stack.first.match(/(.*):(\d+)/)[1..2])
12
+ end
13
+
14
+ # Formats a message that reporst on any test failiures
15
+ def format_failure(message, stack = caller)
16
+ # file, line =
17
+ return "(%s:%0.3d) %s" % [*parse_stack(stack), message]
18
+ end
19
+
20
+ # Formats an exception backtrace to a string.
21
+ def format_exception(raised, msg = "")
22
+ return msg + raised.to_s + "\n" + raised.backtrace.join("\n")
23
+ end
24
+
25
+ # Creates a failiure for the given raised and result state
26
+ # Returns nil if no failure
27
+ def make_failure(res, raised, msg, stack)
28
+ return nil if res
29
+ if raised
30
+ return format_failure(msg || format_exception(raised, "Exception!\n"), stack)
31
+ end
32
+ return format_failure(msg || "Assertion failed!", stack)
33
+ end
34
+
35
+ # Makes a dot for the given raised and result state
36
+ def make_dot(res, raised)
37
+ return res ? '.' : ( raised ? 'E' : 'F')
38
+ end
39
+
40
+ # Calls a block safely with a timeout
41
+ def run_block(delay = 10, &block)
42
+ res, raised = nil, nil
43
+ begin
44
+ Timeout.timeout(delay) do res = block.call ; end
45
+ rescue
46
+ raised = $!
47
+ end
48
+ return res, raised
49
+ end
50
+
51
+ # Test assertion.
52
+ def assert(msg=nil, file=nil, line=nil, delay=10, stack=caller, &block)
53
+ res, raised = run_block(delay, &block)
54
+ @@dots << make_dot(res, raised)
55
+ failure = make_failure(res, raised, msg, stack)
56
+ @@failures << failure if failure
57
+ if msg
58
+ @@messages << ( failure ? msg + " (failed) " : msg)
59
+ end
60
+ res
61
+ end
62
+
63
+ # Results of the tests
64
+ def self.results
65
+ aid = @@dots.join + "\n" + @@failures.join("\n") + "\n"
66
+ col = @@failures.empty? ? :green : :red
67
+ aid << Atto::Ansi.color_string(col, "=" * 78)
68
+ end
69
+
70
+ # Describes the tests
71
+ def self.describe_tests
72
+ @@messages.join(".\n") + ".\n"
73
+ end
74
+
75
+ at_exit {
76
+ puts results unless results.strip.empty?;
77
+ exit @@failures.empty?
78
+ }
79
+ end
80
+ end
data/lib/atto.rb ADDED
@@ -0,0 +1,9 @@
1
+ # Atto is a tiny KISS library full of useful functionality for TDD and BDD.
2
+ module Atto
3
+ # Ansi colors for red/green display after testing.
4
+ autoload :Ansi, 'atto/ansi'
5
+ # Testing
6
+ autoload :Test, 'atto/test'
7
+ # Autorunning tests
8
+ autoload :Run, 'atto/run'
9
+ end
@@ -0,0 +1,27 @@
1
+ require 'atto'
2
+ include Atto::Test
3
+
4
+ assert("Ansi is defined") { Atto::Ansi }
5
+
6
+ assert("Ansi::ATTRIBUTES is defined") { Atto::Ansi::ATTRIBUTES }
7
+
8
+ for attr, value in Atto::Ansi::ATTRIBUTES do
9
+ assert "Attribute #{attr} is colored correctly" do
10
+ Atto::Ansi.color(attr) == ["\e[#{value}m", "\e[0m"]
11
+ end
12
+ end
13
+
14
+ for attr, value in Atto::Ansi::ATTRIBUTES do
15
+ assert "Attribute with text #{attr} is colored correctly" do
16
+ Atto::Ansi.color(attr, "hello") == ["\e[#{value}m", "hello", "\e[0m"]
17
+ end
18
+ end
19
+
20
+ assert "Atto::Ansi#color_string works correctly" do
21
+ Atto::Ansi.color_string(:green, :on_yellow, "This works!") ==
22
+ "\e[32m\e[43mThis works!\e[0m"
23
+ end
24
+
25
+ assert "Atto::Ansi#puts works correctly" do
26
+ (Atto::Ansi.puts :green, :on_yellow, "This works!").nil?
27
+ end
@@ -0,0 +1,22 @@
1
+ require 'atto'
2
+ include Atto::Test
3
+
4
+ assert "Atto is defined" do Atto end
5
+ assert "Atto::Test is defined" do Atto::Test end
6
+ assert "Success can be detected" do true end
7
+ assert "Works with nexted asserts" do
8
+ assert "This is a nested assert" do true end
9
+ end
10
+
11
+ assert "Works with empty description" do assert { true } end
12
+
13
+ assert "Nested asserts keep the return value" do
14
+ assert { 7 } == 7
15
+ end
16
+
17
+ assert "Atto::Test#describe_tests is defined" do Atto::Test.describe_tests end
18
+
19
+
20
+
21
+
22
+
data/test/test_atto.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'atto'
2
+ include Atto::Test
3
+
4
+ assert { Atto }
5
+ assert { Atto::Ansi }
6
+ assert { Atto::Test }
7
+ # assert { Atto::Spec }
8
+
9
+
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
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
10
+ platform: ruby
11
+ authors:
12
+ - Beoran
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-05-07 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: "An ultra-tiny self-contained testing framework. "
22
+ email: beoran@rubyforge.org
23
+ executables:
24
+ - atto
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - Rakefile
31
+ - README
32
+ - lib/atto.rb
33
+ - lib/atto/ansi.rb
34
+ - lib/atto/run.rb
35
+ - lib/atto/test.rb
36
+ - test/test_atto.rb
37
+ - test/atto/test_ansi.rb
38
+ - test/atto/test_test.rb
39
+ - bin/atto
40
+ has_rdoc: true
41
+ homepage: https://github.com/beoran/atto
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options: []
46
+
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ 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
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.7
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: An ultra-tiny self-contained testing framework.
72
+ test_files: []
73
+