railscheck 0.1.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/History.txt ADDED
@@ -0,0 +1,7 @@
1
+ == 0.0.1 2008-03-03
2
+ * Initial proof of concept prerelease as a rails plugin.
3
+
4
+ == 0.0.1 2008-04-13
5
+
6
+ * First proper release as a ruby gem (no longer a rails plugin)
7
+
data/License.txt ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2008 Morten Christensen (mmc[AT/NOSPAM]41concepts[dot]com), 41concepts Aps (www.41concepts.com), Denmark
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to use, copy, modify, merge, include, publish,
6
+ distribute this software ... with the single following
7
+ restriction for commercial software development tool makers:
8
+
9
+ - You may not sell a commercial software development tool that includes
10
+ this software without permission from the copyright holder of this
11
+ software (note: restriction does not apply to free software tools).
12
+ This permission usually involves paying a small fee or making
13
+ a contribution to the project.
14
+
15
+ Furthermore your permission to use this software is subject to
16
+ the following conditions:
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ The above copyright notice and this permission notice shall be
27
+ included in all copies or substantial portions of the Software.
data/Manifest.txt ADDED
@@ -0,0 +1,32 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ TODO.txt
7
+ bin/jrailscheck
8
+ bin/jrailscheck.bat
9
+ bin/railscheck
10
+ bin/railscheck.bat
11
+ config/hoe.rb
12
+ config/requirements.rb
13
+ lib/railscheck.rb
14
+ lib/railscheck/testcase.rb
15
+ lib/railscheck/version.rb
16
+ lib/test/tc_config.rb
17
+ lib/test/tc_database_models.rb
18
+ lib/test/tc_html_and_css.rb
19
+ lib/test/tc_project.rb
20
+ lib/test/tc_views.rb
21
+ log/debug.log
22
+ script/console
23
+ script/destroy
24
+ script/generate
25
+ script/txt2html
26
+ setup.rb
27
+ tasks/deployment.rake
28
+ tasks/environment.rake
29
+ tasks/website.rake
30
+ test/test_helper.rb
31
+ test/test_railscheck.rb
32
+ website/index.html
data/README.txt ADDED
@@ -0,0 +1,112 @@
1
+ = Railscheck - The semi-static Q/A verification tool for your Ruby on Rails projects!
2
+
3
+ == DESCRIPTION
4
+
5
+ This project is a best effort semi-static verifier for your Ruby on Rails projects. Delivered as a Ruby gem it
6
+ provides a shell command task "railscheck" that you can run against your Rails projects to test for a number of
7
+ typical bugs and inconsistencies.
8
+
9
+ It is a law of software development that the earlier you identify a problem the cheaper it is to fix. This project
10
+ aims to help you quickly identify many bugs and inconsistencies as early as possible (thus avoiding unnecessary
11
+ debugging work for you and your development team ; as well as avoiding unnecessary, negative "surprises" for your users).
12
+
13
+ Typical ruby/rails development tools does not provide ANY kind of static verification checks since the problem
14
+ appears to be just about unsolvable in the general case (because of the dynamic nature of Ruby). However for a
15
+ strictly limited domain such as Rails Web Applications, there are actually many potential bugs that can be
16
+ identified statically, or at least (semi-)statically, without having to start the web server and actually
17
+ run the application.
18
+
19
+ Furthermore because of the opinionated nature of Rails, there are many conventions that can be broken and that we can
20
+ check for. Finally rails projects depends on much more than just ruby code - i.e. migrations, database schemas, erb, html,
21
+ css, yaml etc... All of which needs to work for an application to fully function and which is therefore in the scope of this
22
+ this plugin.
23
+
24
+ However, this project can not - and does not attempt to - find all logical/programming errors. As such the gem
25
+ supplements and does not replace existing testing practices such as automated rails tests.
26
+
27
+ == Installation
28
+
29
+ This project is hosted on rubyforge. Install latest version using:
30
+
31
+ "sudo gem install railscheck"
32
+
33
+ == Running
34
+
35
+ The installation will place railscheck executables on path. Invoke the following command for more information.
36
+
37
+ "railscheck -h"
38
+
39
+ The gem contain executables for unix/linux/mac and windows. An alternative "jrailscheck" command is available for jruby
40
+ users.
41
+
42
+ == Features
43
+
44
+ Project:
45
+ * Check validity of Ruby On Rails project structure and existence of key files necessary to
46
+ develop, test and deploy rails projects successfully.
47
+
48
+ Configuration files:
49
+ * Syntax check of all YAML configuration files in project
50
+
51
+ Views:
52
+ * Syntax check of all ERB configuration files in project
53
+
54
+ (X)HTML/CSS:
55
+ * Validation check of all static XHTML/HTML files in project (currently using W3C web services).
56
+ * Validation check of all static CSS files in project (currently using W3C web services).
57
+
58
+ Database:
59
+ * Validates that database is configured correct in project / ability to connect to database.
60
+ * Validates that database migration version corresponds to latest code migration version number in project.
61
+ * Validates that tables with correct names exist for all ActiveRecord model classes in project.
62
+
63
+ == Documentation
64
+
65
+ See "http://railscheck.rubyforge.org/rdoc/" for project RDOC.
66
+
67
+ == Warnings and limitations
68
+
69
+ This plugin assumes that normally safe code in rails projects such as enviroment.rb, intializers, yaml,
70
+ views, models etc. do NOT have dangerous (insane) side-effects that happen just by Ruby loading the
71
+ source file or Ruby retrieving state of objects. If you ever encounter such a bizarre rails project, which
72
+ is extremely unlikely, do NOT run railscheck on the project (and be very, very careful in general about
73
+ what you are doing with the project).
74
+
75
+ This plugin does generally not check dynamic behavior of the application and can as such not replace good testing
76
+ practices, unit-testing etc. Nor does this plugin (currently) test documentation and plugins. The gem is
77
+ targeted for Rails v1.0+ running on Ruby 1.8.6+ compliant implementations (no work will be done to ensure
78
+ compatibility with older rails/ruby versions).
79
+
80
+ == Contributing
81
+
82
+ Any contributions to checks that can be added are welcomed. Please contact undersigned for details.
83
+
84
+ Any added checks that you contribute will be given due credit. However make sure that you assign undersigned
85
+ shared copyright so that I am allowed to release and license your work together with this plugin.
86
+
87
+ == Support
88
+
89
+ There is no formal support for this plugin. Please use railscheck.rubyforge.org to report problems/suggestions and I will look at them in time.
90
+
91
+ == Examples
92
+
93
+ Make sure this plugin is installed and that all your migrations are run. T
94
+
95
+ "railscheck" - to check rails project in current directory.
96
+ "railscheck path-to-your-rails-project" - to check the rails project at the specified path.
97
+
98
+ == Copyrights, Attributions and Author information
99
+
100
+ Copyright (c) 2008 Morten Christensen, 41concepts (www.41concepts.com), Denmark
101
+
102
+ Authors:
103
+ * Morten Christensen, am a software developer from the Danish software company 41concepts (www.41concepts.com). We do
104
+ Ruby/Rails/Java/.NET software development consultancy. Contact me at mmc[AT/NOSPAM]41concepts[dot]com for more
105
+ information.
106
+
107
+ Inspirations and attributions:
108
+ * Fail Early Task written by Mike Naberezny for Advanced Rail Recipes.
109
+ * DZone Snippet Rails task to find code typos in rhtml templates by "dseverin"
110
+
111
+ This software is FREE for both public and commercial use - with the possible exception of commercial
112
+ software development tool makers that require a license (see license file for details).
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
data/TODO.txt ADDED
@@ -0,0 +1,27 @@
1
+ TODO
2
+ =======
3
+
4
+ See below for a list of some future checks that are considered:
5
+
6
+ SHORT/MID TERM:
7
+
8
+ * Verify javascript
9
+ * Syntax check where possible of *.rb
10
+ * Syntax check *.rjs
11
+ * Verify other markup than erb.
12
+ * Additional verification of migration files
13
+ * Syntax check project rake files.
14
+ * Verify *.cgi files.
15
+ * Verify process and script files.
16
+ * Shallow verification of known rails "declarations" such as before_filters, belongs_to etc.
17
+ * Verify integrity of database-related YAML (test) fixtures (corresponding to table columns and all).
18
+ * Compare model constrains against database constrains.
19
+ * Check (some) model validations against data in database (looking for illegal data in database).
20
+
21
+ LONGER TERM:
22
+ * Code analysis checks of ruby and javascriprt code looking for, static detectablable, ruby code
23
+ that may have "simple" errors like accessing a variable before it is declared etc. This
24
+ may in turn open up for many more features.
25
+
26
+
27
+ Copyright (c) 2008 Morten Christensen (mmc[AT/NOSPAM]41concepts[dot]com), 41concepts Aps (www.41concepts.com), Denmark
data/bin/jrailscheck ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env jruby
2
+ # Copyright (c) 2008. Morten M. Christensen, 41concepts Aps. All rights reserved.
3
+ require File.dirname(__FILE__) + '/../lib/railscheck'
@@ -0,0 +1,3 @@
1
+ @ECHO OFF
2
+ REM # Copyright (c) 2008. Morten M. Christensen, 41concepts Aps. All rights reserved.
3
+ jruby.exe ../lib/railscheck.rb %1 %2 %3 %4 %5 %6 %7 %8 %9
data/bin/railscheck ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (c) 2008. Morten M. Christensen, 41concepts Aps. All rights reserved.
3
+ require File.dirname(__FILE__) + '/../lib/railscheck'
@@ -0,0 +1,3 @@
1
+ @ECHO OFF
2
+ REM # Copyright (c) 2008. Morten M. Christensen, 41concepts Aps. All rights reserved.
3
+ ruby.exe ../lib/railscheck.rb %1 %2 %3 %4 %5 %6 %7 %8 %9
data/config/hoe.rb ADDED
@@ -0,0 +1,70 @@
1
+ require 'railscheck/version'
2
+
3
+ AUTHOR = 'Morten M. Christensen / 41concepts' # can also be an array of Authors
4
+ EMAIL = "mmc@41concepts.com"
5
+ DESCRIPTION = "Static verifier for rails 2.0+ projects"
6
+ GEM_NAME = 'railscheck' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'railscheck' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+
11
+ @config_file = "~/.rubyforge/user-config.yml"
12
+ @config = nil
13
+ RUBYFORGE_USERNAME = "mmc"
14
+ def rubyforge_username
15
+ unless @config
16
+ begin
17
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
18
+ rescue
19
+ puts <<-EOS
20
+ ERROR: No rubyforge config file found: #{@config_file}
21
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
22
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
23
+ EOS
24
+ exit
25
+ end
26
+ end
27
+ RUBYFORGE_USERNAME.replace @config["username"]
28
+ end
29
+
30
+
31
+ REV = nil
32
+ # UNCOMMENT IF REQUIRED:
33
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
34
+ VERS = Railscheck::VERSION::STRING + (REV ? ".#{REV}" : "")
35
+ RDOC_OPTS = ['--quiet', '--title', 'railscheck documentation',
36
+ "--opname", "index.html",
37
+ "--line-numbers",
38
+ "--main", "README",
39
+ "--inline-source"]
40
+
41
+ class Hoe
42
+ def extra_deps
43
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
44
+ @extra_deps
45
+ end
46
+ end
47
+
48
+ # Generate all the Rake tasks
49
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
50
+ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
51
+ p.developer(AUTHOR, EMAIL)
52
+ p.description = DESCRIPTION
53
+ p.summary = DESCRIPTION
54
+ p.url = HOMEPATH
55
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
56
+ p.test_globs = ["test/**/test_*.rb"]
57
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
58
+
59
+ # == Optional
60
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
61
+ #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
62
+
63
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
64
+
65
+ end
66
+
67
+ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
68
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
69
+ $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
70
+ $hoe.rsync_args = '-av --delete --ignore-errors'
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
@@ -0,0 +1,16 @@
1
+ require 'test/unit'
2
+
3
+ # Base class for all testcases in railscheck. Put all general behavior for Railscheck
4
+ # testcases here.
5
+ module Railscheck
6
+ class TestCase < ::Test::Unit::TestCase
7
+ # Redefine defqult_test so we don't get any errors about missing test in our base class.
8
+ def default_test
9
+ # Do nothing
10
+ end
11
+
12
+ def warn(msg)
13
+ puts "Warning: "+msg
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ module Railscheck #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
data/lib/railscheck.rb ADDED
@@ -0,0 +1,93 @@
1
+ begin
2
+ require 'rubygems'
3
+ rescue LoadError
4
+ # no rubygems to load, so we fail silently
5
+ end
6
+
7
+ require 'optparse'
8
+ $:.unshift(File.dirname(__FILE__)) unless
9
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
10
+
11
+ require 'railscheck/version'
12
+
13
+ module Railscheck
14
+ puts "Railscheck "+Railscheck::VERSION::STRING+" (nb. help & more information avilable with -h argument):"
15
+
16
+ OPTIONS = {
17
+ :include_test_files => '.*',
18
+ :exclude_test_files => ''
19
+ }
20
+ MANDATORY_OPTIONS = %w( )
21
+
22
+ parser = OptionParser.new do |opts|
23
+ opts.banner = <<BANNER
24
+ This gem is a best effort semi-static verifier for your Ruby on Rails projects
25
+ freely provided as an open source project by 41concepts (www.41concepts.com).
26
+
27
+ Usage: #{File.basename($0)} [options] [rails-project-path]
28
+
29
+ Defailt behavior is run all tests against the the rails project in the current directory (if no arguments are provided).
30
+
31
+ See \"http://railscheck.rubyforge.org\" for more information.
32
+
33
+ Optional options are:
34
+ BANNER
35
+
36
+ opts.separator ""
37
+ opts.on("-i", "--include_test_files=txt", String,
38
+ "Only include test files satisfying specified the regular expresssion string (without //)"
39
+ ) { |OPTIONS[:include_test_files]| }
40
+
41
+ opts.on("-x", "--exclude_test_files=txt", String,
42
+ "Exclude test files satisfying specified the regular expresssion string (without //)"
43
+ ) { |OPTIONS[:exclude_test_files]| }
44
+
45
+ opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
46
+ opts.parse!(ARGV)
47
+
48
+ if MANDATORY_OPTIONS && MANDATORY_OPTIONS.find { |option| OPTIONS[option.to_sym].nil? }
49
+ puts opts; exit
50
+ end
51
+ end
52
+
53
+ has_project_dir_arg = (ARGV.length>0)
54
+ railscheck_root_dir = has_project_dir_arg ? ARGV[0] : '.' # Use first non-option argument at root
55
+
56
+ puts "No directory provided. Using '"+railscheck_root_dir+"'" if !has_project_dir_arg
57
+
58
+ begin
59
+ require "#{railscheck_root_dir}/config/boot"
60
+ require 'environment'
61
+ rescue LoadError => e
62
+ puts "Could not locate RoR project at \"#{railscheck_root_dir}\"."
63
+ exit (-1)
64
+ end
65
+
66
+ puts "Booted RoR #{Rails::VERSION::STRING} project at \"#{RAILS_ROOT}\"."
67
+ puts "Running all railscheck tests satifying /#{OPTIONS[:include_test_files]}/ " + (OPTIONS[:exclude_test_files].empty? ? ":" : "and not satifying /#{OPTIONS[:exclude_test_files]}/:" )
68
+
69
+ # Get all test files from test folder and apply include/exclude filters.
70
+ tests = []
71
+ Dir[File.join(File.dirname(__FILE__), "test/tc_*.rb")].each do |tstfile|
72
+ tst_basename = File.basename(tstfile)
73
+ tests << tstfile if (tst_basename =~ Regexp.new(OPTIONS[:include_test_files])) and (OPTIONS[:exclude_test_files].empty? || !(tst_basename =~ Regexp.new(OPTIONS[:exclude_test_files])))
74
+ end
75
+
76
+ require 'test/unit/testsuite'
77
+
78
+ #test_suite = Test::Unit::TestSuite.new("Railscheck testsuite")
79
+ #tests.sort.each do |tst|
80
+ # puts "Loading test file \"#{tst}\"."
81
+ # test_suite << require(tst).suite
82
+ #end
83
+ #require 'test/unit/ui/console/testrunner'
84
+ #::Test::Unit::UI::Console::TestRunner.run(test_suite)
85
+
86
+ # Run all tests in sorted order.
87
+ tests.sort.each do |tst|
88
+ puts "Loading test file \"#{tst}\"."
89
+ require tst
90
+ end
91
+
92
+ require 'test/unit/ui/console/testrunner'
93
+ end # module Railscheck
@@ -0,0 +1,16 @@
1
+ require 'railscheck/testcase'
2
+
3
+ module Railscheck
4
+ module Test
5
+ class Config < Railscheck::TestCase
6
+ # Test that every yaml file in the project can parse (except vendor plugins/rails).
7
+ def test_all_yaml_can_parse
8
+ (Dir["#{RAILS_ROOT}/**/*.yml"]-Dir["#{RAILS_ROOT}/vendor/**/*.yml"]).each do |fname|
9
+ assert_nothing_raised("Could not parse file \"#{fname}\".") do
10
+ raise StandardError.new("Parse failed") if YAML.parse_file(fname)==nil
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,43 @@
1
+ require 'railscheck/testcase'
2
+
3
+ module Railscheck
4
+ module Test
5
+ class DataBaseModels < Railscheck::TestCase
6
+ # Test that database connection can be established.
7
+ def test_database_connection_working
8
+ assert File.file?("#{RAILS_ROOT}/config/database.yml"), "Database configuration file database.yml must be present"
9
+
10
+ assert_nothing_raised("Could not open database connection") do
11
+ ActiveRecord::Base.establish_connection
12
+ ActiveRecord::Base.connection.select_all('SHOW TABLES')
13
+ end
14
+ end
15
+
16
+ # Test that all migrations has been migrated.
17
+ def test_database_consistent_with_migration_version
18
+ db_version = ActiveRecord::Migrator.current_version rescue 0
19
+ highest_migration_version_in_project = Dir.glob("#{RAILS_ROOT}/db/migrate/*.rb" ).map { |f|
20
+ f.match(/(\d+)_.*\.rb$/) ? $1.to_i : 0
21
+ }.max
22
+
23
+ assert_equal highest_migration_version_in_project, db_version, "Database version is not up-to-date with migrations (forgot to run db:migrate?)."
24
+ end
25
+
26
+ # Check that correctly named database tables exist for each rails model
27
+ def test_database_tables_and_models_consistency
28
+ Dir["#{RAILS_ROOT}/app/models/*rb"].each do |fname|
29
+ class_names = load(fname, false)
30
+ class_names.each do |class_name|
31
+ c = Object.const_get(class_name)
32
+ # Note: "c.kind_of?(ActiveRecord::Base)" not working here so do alt. check instead.
33
+ if (c.respond_to? 'abstract_class') && !c.abstract_class? &&
34
+ (c.respond_to? 'descends_from_active_record?') #&& c.descends_from_active_record?
35
+ assert c.table_exists?, "Error - Could not find database table #{c.table_name} corresponding to rails model #{c.name}"
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,55 @@
1
+ require 'railscheck/testcase'
2
+ require 'w3c_validators'
3
+
4
+ module Railscheck
5
+ module Test
6
+ class HtmlAndCss < Railscheck::TestCase
7
+ include W3CValidators
8
+
9
+ MAX_VALIDATION_ERRORS = 3 # Filter for how many errors to show.
10
+ MAX_VALIDATION_WARNINGS = 3 # Filter for how many warnings to show.
11
+
12
+ # Test that static CSS files validates using W3C online service.
13
+ def test_all_css_validates
14
+ @validator = CSSValidator.new
15
+
16
+ Dir["#{RAILS_ROOT}/public/**/*.css", "#{RAILS_ROOT}/doc/**/*.css"].each do |fname|
17
+ results = @validator.validate_file(fname)
18
+
19
+ validation_errors = results.errors.length
20
+ validation_errors_to_show = [results.errors.length, MAX_VALIDATION_ERRORS].min
21
+
22
+ validation_warnings = results.warnings.length
23
+ validation_warnings_to_show = [results.warnings.length, MAX_VALIDATION_WARNINGS].min
24
+
25
+ assert_equal 0, results.errors.length, "#{validation_errors} validation error(s) in \"#{fname}\". Showing #{validation_errors_to_show}: "+results.errors[0..validation_errors_to_show-1].join("\n")
26
+
27
+ if (validation_warnings!=0)
28
+ warn "#{validation_warnings} validation warning(s) in \"#{fname}\". Showing #{validation_warnings_to_show}: "+results.warnings[0..validation_warnings_to_show-1].join("\n")
29
+ end
30
+ end
31
+ end
32
+
33
+ # Test that static HTML files validates using W3C online service.
34
+ def test_all_html_validates
35
+ @validator = MarkupValidator.new
36
+
37
+ Dir["#{RAILS_ROOT}/public/**/*.html", "#{RAILS_ROOT}/public/**/*.xhtml", "#{RAILS_ROOT}/doc/**/*.html", "#{RAILS_ROOT}/doc/**/*.xhtml"].each do |fname|
38
+ results = @validator.validate_file(fname)
39
+
40
+ validation_errors = results.errors.length
41
+ validation_errors_to_show = [results.errors.length, MAX_VALIDATION_ERRORS].min
42
+
43
+ validation_warnings = results.warnings.length
44
+ validation_warnings_to_show = [results.warnings.length, MAX_VALIDATION_WARNINGS].min
45
+
46
+ assert_equal 0, results.errors.length, "#{validation_errors} validation error(s) in \"#{fname}\". Showing #{validation_errors_to_show}: "+results.errors[0..validation_errors_to_show-1].join("\n")
47
+
48
+ if (validation_warnings!=0)
49
+ warn "#{validation_warnings} validation warning(s) in \"#{fname}\". Showing #{validation_warnings_to_show}: "+results.warnings[0..validation_warnings_to_show-1].join("\n")
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,106 @@
1
+ require 'railscheck/testcase'
2
+
3
+ module Railscheck
4
+ module Test
5
+ class Project < Railscheck::TestCase
6
+ # Verify rails project structure/files taking into account various rails versions, build-in test/rspec usage etc.
7
+ def test_rails_project
8
+ root = RAILS_ROOT
9
+
10
+ # Check for key rails 1.0+ directories that must exist for all complete and valid projects (skip optional ones):
11
+ ["#{root}/app", "#{root}/app/controllers", "#{root}/app/helpers", "#{root}/app/models", "#{root}/app/views", "#{root}/app/views/layouts",
12
+ "#{root}/config", "#{root}/config/environments",
13
+ "#{root}/db",
14
+ "#{root}/lib", "#{root}/lib/tasks",
15
+ "#{root}/log",
16
+ "#{root}/public", "#{root}/public/images", "#{root}/public/javascripts","#{root}/public/stylesheets",
17
+ "#{root}/script", "#{root}/script/performance", "#{root}/script/process",
18
+ "#{root}/vendor", "#{root}/vendor/plugins"
19
+ ].each do |dir|
20
+ assert File.directory?(dir), "Error - missing rails directory #{dir}"
21
+ end
22
+
23
+ # Check for key rails 2.0+ directories that must exist for all complete and valid projects (skip optional ones):
24
+ if Rails::VERSION::MAJOR >=2
25
+ ["#{root}/config/initializers"
26
+ ].each do |dir|
27
+ assert File.directory?(dir), "Error - missing rails directory #{dir}"
28
+ end
29
+ end
30
+
31
+ # Build-in test or rspec can be used so we need to verify which one (or both) is used.
32
+ test = File.directory?("#{root}/test")
33
+ rspec = File.directory?("#{root}/spec")
34
+
35
+ # Check that build-in test or rspec test directories exist.
36
+ assert test || rspec, "Either test or spec directories should exist for testing purposes. Both are missing."
37
+
38
+ # Check for build-in test directories (may not all exist so issue warnings only)
39
+ if test
40
+ ["#{root}/test/fixtures", "#{root}/test/functional", "#{root}/test/integration",
41
+ "#{root}/test/mocks", "#{root}/test/mocks/development", "#{root}/test/mocks/test",
42
+ ].each do |dir|
43
+ "Missing rails directory #{dir}" if !File.directory?(dir)
44
+ end
45
+ end
46
+
47
+ # Check for rspec directories (may not all exist so issue warnings only)
48
+ if rspec
49
+ [ #TODO: Add any expected directories here.
50
+ ].each do |dir|
51
+ "Missing rails rspec directory #{dir}" if !File.directory?(dir)
52
+ end
53
+ end
54
+
55
+ # Check for vital rails 1.0+ files that must exist for all complete and valid projects (skip optional ones):
56
+ ["#{root}/app/controllers/application.rb",
57
+ "#{root}/config/boot.rb", "#{root}/config/database.yml", "#{root}/config/environment.rb", "#{root}/config/routes.rb",
58
+ "#{root}/config/environments/development.rb", "#{root}/config/environments/test.rb", "#{root}/config/environments/production.rb",
59
+ "#{root}/script/about", "#{root}/script/console", "#{root}/script/console", "#{root}/script/destroy", "#{root}/script/generate",
60
+ "#{root}/script/plugin", "#{root}/script/runner", "#{root}/script/server",
61
+ "#{root}/script/performance/benchmarker", "#{root}/script/performance/profiler",
62
+ "#{root}/script/process/inspector", "#{root}/script/process/reaper", "#{root}/script/process/spawner",
63
+ ].each do |file|
64
+ assert File.file?(file), "Error - missing rails file #{file}"
65
+ end
66
+
67
+ # Check for vital rails 2.0+ files that must exist for all complete and valid projects (skip optional ones):
68
+ if Rails::VERSION::MAJOR >=2
69
+ [ #TODO: Add any rails 2.x only files here
70
+ ].each do |file|
71
+ assert File.file?(file), "Error - missing rails file #{file}"
72
+ end
73
+ end
74
+
75
+ # Check for optional build-in test files.
76
+ if test
77
+ ["#{root}/test/test_helper.rb"
78
+ ].each do |file|
79
+ warn "Missing rails file #{file}" if !File.file?(file)
80
+ end
81
+ end
82
+
83
+ # Check for optional rspec files.
84
+ if rspec
85
+ ["#{root}/spec/spec_helper.rb"
86
+ ].each do |file|
87
+ warn "Missing rails rspec file #{file}" if !File.file?(file)
88
+ end
89
+ end
90
+ end # test_rails_project
91
+
92
+ # test that installed plugins have the required minimum file structure.
93
+ def test_plugins_valid
94
+ Dir["#{RAILS_ROOT}/vendor/plugins/*"].each do |plugindir|
95
+ assert File.directory?(plugindir), "Error - \"#{plugindir}\" is not a directory. Project vendor directory may only contain directories."
96
+
97
+ lib_dir = File.join(plugindir, "lib")
98
+ init_file = File.join(plugindir, "init.rb")
99
+
100
+ assert File.directory?(lib_dir), "Error no lib sub-directory in plugin at \"#{plugindir}\""
101
+ assert File.file?(init_file), "Error no init file in plugin at \"#{plugindir}\""
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end