├── Gemfile ├── .gitignore ├── README.md ├── Indexfile ├── .index ├── LICENSE.txt ├── lib └── rubytest │ └── format │ └── outline.rb └── .gemspec /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "rubytest", ">= 0.8.0" 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .reap/digest 3 | .yardoc 4 | doc/ 5 | log/ 6 | pkg/ 7 | tmp/ 8 | web/ 9 | QED.rdoc 10 | QED.md 11 | Gemfile.lock 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Outline Test Report Format 2 | 3 | This is a test report format plugin for Rubytest. 4 | 5 | 6 | ## Copyrights 7 | 8 | Copyright 2011 Rubyworks. All rights reserved. 9 | 10 | 11 | -------------------------------------------------------------------------------- /Indexfile: -------------------------------------------------------------------------------- 1 | --- 2 | name: 3 | rubytest-outline 4 | 5 | version: 6 | 0.1.0 7 | 8 | title: 9 | Rubytest Outline Report Format 10 | 11 | summary: 12 | Outline test report format for Rubytest. 13 | 14 | description: 15 | This is an outline test report format for the Rubytest metaframework. 16 | 17 | resources: 18 | home: http://rubyworks.github.com/rubytest-outline 19 | code: http://github.com/rubyworks/rubytest-outline 20 | mail: http://groups.google.com/group/rubyworks-mailinglist 21 | 22 | repositories: 23 | upstream: git@github.com:rubyworks/rubytest-outline.git 24 | 25 | authors: 26 | - trans 27 | 28 | created: 2011-07-23 29 | 30 | copyrights: 31 | - 2011 RubyWorks (BSD-2-Clause) 32 | 33 | -------------------------------------------------------------------------------- /.index: -------------------------------------------------------------------------------- 1 | --- 2 | revision: 2013 3 | type: ruby 4 | sources: 5 | - Indexfile 6 | - Gemfile 7 | authors: 8 | - name: trans 9 | email: transfire@gmail.com 10 | organizations: [] 11 | requirements: 12 | - version: '>= 0.8.0' 13 | name: rubytest 14 | conflicts: [] 15 | alternatives: [] 16 | resources: 17 | - type: home 18 | uri: http://rubyworks.github.com/rubytest-outline 19 | label: Homepage 20 | - type: code 21 | uri: http://github.com/rubyworks/rubytest-outline 22 | label: Source Code 23 | - type: mail 24 | uri: http://groups.google.com/group/rubyworks-mailinglist 25 | label: Mailing List 26 | repositories: 27 | - name: upstream 28 | scm: git 29 | uri: git@github.com:rubyworks/rubytest-outline.git 30 | categories: [] 31 | copyrights: 32 | - holder: RubyWorks 33 | year: '2011' 34 | license: BSD-2-Clause 35 | customs: [] 36 | paths: 37 | lib: 38 | - lib 39 | name: rubytest-outline 40 | title: Rubytest Outline Report Format 41 | version: 0.1.0 42 | summary: Outline test report format for Rubytest. 43 | description: This is an outline test report format for the Rubytest metaframework. 44 | created: '2011-07-23' 45 | date: '2014-07-18' 46 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | (BSD-2-Clause License) 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 14 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 16 | COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 17 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 21 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 22 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | -------------------------------------------------------------------------------- /lib/rubytest/format/outline.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | require 'ansi' 3 | 4 | module Test::Reporters 5 | 6 | ## 7 | # Outline reporter. 8 | # 9 | class Outline < Abstract 10 | 11 | # 12 | def begin_suite(suite) 13 | @tab = 0 14 | @start_time = Time.now 15 | @start_test_cache = {} 16 | 17 | timer_reset 18 | end 19 | 20 | # 21 | def begin_case(tc) 22 | lines = tc.to_s.split("\n") 23 | label = lines.shift 24 | if tc.respond_to?(:type) 25 | tabs "#{tc.type}: #{label}".ansi(:bold) 26 | tabs lines.join("\n"), 2 unless lines.empty? 27 | else 28 | tabs "#{label}".ansi(:bold) 29 | tabs lines.join("\n"), 2 unless lines.empty? 30 | end 31 | @tab += 2 32 | end 33 | 34 | # 35 | def begin_test(test) 36 | if test.respond_to?(:topic) && test.topic 37 | topic = test.topic.to_s 38 | @start_test_cache[topic] ||= ( 39 | tabs "#{topic}" 40 | true 41 | ) 42 | end 43 | timer_reset 44 | end 45 | 46 | # 47 | # 48 | def pass(test) 49 | tabs "#{test}".ansi(:green) 50 | end 51 | 52 | # 53 | def fail(test, exception) 54 | tabs "#{test}".ansi(:red) 55 | 56 | s = [] 57 | s << "#{exception}" 58 | s << "#{file_and_line(exception)}" 59 | s << code(exception) 60 | #puts " #{exception.backtrace[0]}" 61 | tabs s.join("\n"), 4 62 | end 63 | 64 | # 65 | def error(test, exception) 66 | tabs "#{test}".ansi(:red, :bold) 67 | 68 | s = [] 69 | s << "#{exception.class}" 70 | s << "#{exception}" 71 | s << "#{file_and_line(exception)}" 72 | s << code(exception) 73 | #s << trace.join("\n") unless trace.empty? 74 | tabs s.join("\n"), 4 75 | end 76 | 77 | # 78 | def todo(test, exception) 79 | tabs "#{test}".ansi(:yellow) 80 | tabs "#{file_and_line(exception)}", 4 81 | end 82 | 83 | # 84 | def omit(test, exception) 85 | tabs "#{test}".ansi(:cyan) 86 | end 87 | 88 | # 89 | def end_case(tcase) 90 | @tab -= 2 91 | end 92 | 93 | # 94 | def end_suite(suite) 95 | puts 96 | 97 | #unless record[:omit].empty? 98 | # puts "\nOMITTED:\n\n" 99 | # puts record[:omit].map{ |u| u.to_s }.sort.join(' ') 100 | # puts 101 | #end 102 | 103 | #unless record[:todo].empty? 104 | # puts "\nPENDING:\n\n" 105 | # record[:pending].each do |test, exception| 106 | # puts "#{test}".tabto(4) 107 | # puts "#{file_and_line(exception)}".tabto(4) 108 | # puts 109 | # end 110 | #end 111 | 112 | #unless record[:fail].empty? 113 | # puts "\nFAILURES:\n\n" 114 | # record[:fail].reverse_each do |test, exception| 115 | # 116 | # s = [] 117 | # s << "#{test}".ansi(:red) 118 | # s << "#{file_and_line(exception)}".ansi(:bold) 119 | # s << "#{exception}" 120 | # s << code_snippet(exception) 121 | # #puts " #{exception.backtrace[0]}" 122 | # puts s.join("\n").tabto(4) 123 | # end 124 | #end 125 | 126 | #unless record[:error].empty? 127 | # puts "\nERRORS:\n\n" 128 | # record[:error].reverse_each do |test, exception| 129 | # trace = clean_backtrace(exception)[1..-1] 130 | # 131 | # s = [] 132 | # s << "#{test}".ansi(:red, :bold) 133 | # s << "#{exception.class} @ #{file_and_line(exception)}".ansi(:bold) 134 | # s << "#{exception}" 135 | # s << code_snippet(exception) 136 | # #s << trace.join("\n") unless trace.empty? 137 | # puts s.join("\n").tabto(4) 138 | # end 139 | #end 140 | 141 | puts 142 | puts timestamp 143 | puts 144 | puts tally 145 | end 146 | 147 | # 148 | def clock 149 | secs = Time.now - @start_time 150 | return "%0.5fs" % [secs.to_s] 151 | end 152 | 153 | # 154 | def timer 155 | secs = Time.now - @time 156 | @time = Time.now 157 | return "%0.5fs" % [secs.to_s] 158 | end 159 | 160 | # 161 | def timer_reset 162 | @time = Time.now 163 | end 164 | 165 | # 166 | def tabs(str, indent=0) 167 | if str 168 | puts(str.tabto(@tab + indent)) 169 | else 170 | puts 171 | end 172 | end 173 | 174 | end 175 | 176 | end 177 | 178 | 179 | 180 | 181 | =begin 182 | if cover? 183 | 184 | unless uncovered_cases.empty? 185 | unc = uncovered_cases.map do |mod| 186 | yellow(mod.name) 187 | end.join(", ") 188 | puts "\nUncovered Cases: " + unc 189 | end 190 | 191 | unless uncovered_units.empty? 192 | unc = uncovered_units.map do |unit| 193 | yellow(unit) 194 | end.join(", ") 195 | puts "\nUncovered Units: " + unc 196 | end 197 | 198 | #unless uncovered.empty? 199 | # unc = uncovered.map do |unit| 200 | # yellow(unit) 201 | # end.join(", ") 202 | # puts "\nUncovered: " + unc 203 | #end 204 | 205 | unless undefined_units.empty? 206 | unc = undefined_units.map do |unit| 207 | yellow(unit) 208 | end.join(", ") 209 | puts "\nUndefined Units: " + unc 210 | end 211 | 212 | end 213 | =end 214 | 215 | -------------------------------------------------------------------------------- /.gemspec: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'yaml' 4 | require 'pathname' 5 | 6 | module Indexer 7 | 8 | # Convert index data into a gemspec. 9 | # 10 | # Notes: 11 | # * Assumes all executables are in bin/. 12 | # * Does not yet handle default_executable setting. 13 | # * Does not yet handle platform setting. 14 | # * Does not yet handle required_ruby_version. 15 | # * Support for rdoc entries is weak. 16 | # 17 | class GemspecExporter 18 | 19 | # File globs to include in package --unless a manifest file exists. 20 | FILES = ".index .yardopts alt bin data demo ext features lib man spec test try* [A-Z]*.*" unless defined?(FILES) 21 | 22 | # File globs to omit from FILES. 23 | OMIT = "Config.rb" unless defined?(OMIT) 24 | 25 | # Standard file patterns. 26 | PATTERNS = { 27 | :root => '{.index,Gemfile}', 28 | :bin => 'bin/*', 29 | :lib => 'lib/{**/}*', #.rb', 30 | :ext => 'ext/{**/}extconf.rb', 31 | :doc => '*.{txt,rdoc,md,markdown,tt,textile}', 32 | :test => '{test,spec}/{**/}*.rb' 33 | } unless defined?(PATTERNS) 34 | 35 | # For which revision of indexer spec is this converter intended? 36 | REVISION = 2013 unless defined?(REVISION) 37 | 38 | # 39 | def self.gemspec 40 | new.to_gemspec 41 | end 42 | 43 | # 44 | attr :metadata 45 | 46 | # 47 | def initialize(metadata=nil) 48 | @root_check = false 49 | 50 | if metadata 51 | root_dir = metadata.delete(:root) 52 | if root_dir 53 | @root = root_dir 54 | @root_check = true 55 | end 56 | metadata = nil if metadata.empty? 57 | end 58 | 59 | @metadata = metadata || YAML.load_file(root + '.index') 60 | 61 | if @metadata['revision'].to_i != REVISION 62 | warn "This gemspec exporter was not designed for this revision of index metadata." 63 | end 64 | end 65 | 66 | # 67 | def has_root? 68 | root ? true : false 69 | end 70 | 71 | # 72 | def root 73 | return @root if @root || @root_check 74 | @root_check = true 75 | @root = find_root 76 | end 77 | 78 | # 79 | def manifest 80 | return nil unless root 81 | @manifest ||= Dir.glob(root + 'manifest{,.txt}', File::FNM_CASEFOLD).first 82 | end 83 | 84 | # 85 | def scm 86 | return nil unless root 87 | @scm ||= %w{git hg}.find{ |m| (root + ".#{m}").directory? }.to_sym 88 | end 89 | 90 | # 91 | def files 92 | return [] unless root 93 | @files ||= \ 94 | if manifest 95 | File.readlines(manifest). 96 | map{ |line| line.strip }. 97 | reject{ |line| line.empty? || line[0,1] == '#' } 98 | else 99 | list = [] 100 | Dir.chdir(root) do 101 | FILES.split(/\s+/).each do |pattern| 102 | list.concat(glob(pattern)) 103 | end 104 | OMIT.split(/\s+/).each do |pattern| 105 | list = list - glob(pattern) 106 | end 107 | end 108 | list 109 | end.select{ |path| File.file?(path) }.uniq 110 | end 111 | 112 | # 113 | def glob_files(pattern) 114 | return [] unless root 115 | Dir.chdir(root) do 116 | Dir.glob(pattern).select do |path| 117 | File.file?(path) && files.include?(path) 118 | end 119 | end 120 | end 121 | 122 | def patterns 123 | PATTERNS 124 | end 125 | 126 | def executables 127 | @executables ||= \ 128 | glob_files(patterns[:bin]).map do |path| 129 | File.basename(path) 130 | end 131 | end 132 | 133 | def extensions 134 | @extensions ||= \ 135 | glob_files(patterns[:ext]).map do |path| 136 | File.basename(path) 137 | end 138 | end 139 | 140 | def name 141 | metadata['name'] || metadata['title'].downcase.gsub(/\W+/,'_') 142 | end 143 | 144 | def homepage 145 | page = ( 146 | metadata['resources'].find{ |r| r['type'] =~ /^home/i } || 147 | metadata['resources'].find{ |r| r['name'] =~ /^home/i } || 148 | metadata['resources'].find{ |r| r['name'] =~ /^web/i } 149 | ) 150 | page ? page['uri'] : false 151 | end 152 | 153 | def licenses 154 | metadata['copyrights'].map{ |c| c['license'] }.compact 155 | end 156 | 157 | def require_paths 158 | paths = metadata['paths'] || {} 159 | paths['load'] || ['lib'] 160 | end 161 | 162 | # 163 | # Convert to gemnspec. 164 | # 165 | def to_gemspec 166 | if has_root? 167 | Gem::Specification.new do |gemspec| 168 | to_gemspec_data(gemspec) 169 | to_gemspec_paths(gemspec) 170 | end 171 | else 172 | Gem::Specification.new do |gemspec| 173 | to_gemspec_data(gemspec) 174 | to_gemspec_paths(gemspec) 175 | end 176 | end 177 | end 178 | 179 | # 180 | # Convert pure data settings. 181 | # 182 | def to_gemspec_data(gemspec) 183 | gemspec.name = name 184 | gemspec.version = metadata['version'] 185 | gemspec.summary = metadata['summary'] 186 | gemspec.description = metadata['description'] 187 | 188 | metadata['authors'].each do |author| 189 | gemspec.authors << author['name'] 190 | 191 | if author.has_key?('email') 192 | if gemspec.email 193 | gemspec.email << author['email'] 194 | else 195 | gemspec.email = [author['email']] 196 | end 197 | end 198 | end 199 | 200 | gemspec.licenses = licenses 201 | 202 | requirements = metadata['requirements'] || [] 203 | requirements.each do |req| 204 | next if req['optional'] 205 | next if req['external'] 206 | 207 | name = req['name'] 208 | groups = req['groups'] || [] 209 | 210 | version = gemify_version(req['version']) 211 | 212 | if groups.empty? or groups.include?('runtime') 213 | # populate runtime dependencies 214 | if gemspec.respond_to?(:add_runtime_dependency) 215 | gemspec.add_runtime_dependency(name,*version) 216 | else 217 | gemspec.add_dependency(name,*version) 218 | end 219 | else 220 | # populate development dependencies 221 | if gemspec.respond_to?(:add_development_dependency) 222 | gemspec.add_development_dependency(name,*version) 223 | else 224 | gemspec.add_dependency(name,*version) 225 | end 226 | end 227 | end 228 | 229 | # convert external dependencies into gemspec requirements 230 | requirements.each do |req| 231 | next unless req['external'] 232 | gemspec.requirements << ("%s-%s" % req.values_at('name', 'version')) 233 | end 234 | 235 | gemspec.homepage = homepage 236 | gemspec.require_paths = require_paths 237 | gemspec.post_install_message = metadata['install_message'] 238 | end 239 | 240 | # 241 | # Set gemspec settings that require a root directory path. 242 | # 243 | def to_gemspec_paths(gemspec) 244 | gemspec.files = files 245 | gemspec.extensions = extensions 246 | gemspec.executables = executables 247 | 248 | if Gem::VERSION < '1.7.' 249 | gemspec.default_executable = gemspec.executables.first 250 | end 251 | 252 | gemspec.test_files = glob_files(patterns[:test]) 253 | 254 | unless gemspec.files.include?('.document') 255 | gemspec.extra_rdoc_files = glob_files(patterns[:doc]) 256 | end 257 | end 258 | 259 | # 260 | # Return a copy of this file. This is used to generate a local 261 | # .gemspec file that can automatically read the index file. 262 | # 263 | def self.source_code 264 | File.read(__FILE__) 265 | end 266 | 267 | private 268 | 269 | def find_root 270 | root_files = patterns[:root] 271 | if Dir.glob(root_files).first 272 | Pathname.new(Dir.pwd) 273 | elsif Dir.glob("../#{root_files}").first 274 | Pathname.new(Dir.pwd).parent 275 | else 276 | #raise "Can't find root of project containing `#{root_files}'." 277 | warn "Can't find root of project containing `#{root_files}'." 278 | nil 279 | end 280 | end 281 | 282 | def glob(pattern) 283 | if File.directory?(pattern) 284 | Dir.glob(File.join(pattern, '**', '*')) 285 | else 286 | Dir.glob(pattern) 287 | end 288 | end 289 | 290 | def gemify_version(version) 291 | case version 292 | when /^(.*?)\+$/ 293 | ">= #{$1}" 294 | when /^(.*?)\-$/ 295 | "< #{$1}" 296 | when /^(.*?)\~$/ 297 | "~> #{$1}" 298 | else 299 | version 300 | end 301 | end 302 | 303 | end 304 | 305 | end 306 | 307 | Indexer::GemspecExporter.gemspec --------------------------------------------------------------------------------