tarantula-rails3 0.3.3

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.
Files changed (68) hide show
  1. data/CHANGELOG +49 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +161 -0
  4. data/Rakefile +83 -0
  5. data/VERSION.yml +4 -0
  6. data/examples/example_helper.rb +57 -0
  7. data/examples/relevance/core_extensions/ellipsize_example.rb +19 -0
  8. data/examples/relevance/core_extensions/file_example.rb +8 -0
  9. data/examples/relevance/core_extensions/response_example.rb +29 -0
  10. data/examples/relevance/core_extensions/test_case_example.rb +20 -0
  11. data/examples/relevance/tarantula/attack_handler_example.rb +29 -0
  12. data/examples/relevance/tarantula/basic_attack_example.rb +12 -0
  13. data/examples/relevance/tarantula/crawler_example.rb +375 -0
  14. data/examples/relevance/tarantula/form_example.rb +50 -0
  15. data/examples/relevance/tarantula/form_submission_example.rb +171 -0
  16. data/examples/relevance/tarantula/html_document_handler_example.rb +43 -0
  17. data/examples/relevance/tarantula/html_report_helper_example.rb +46 -0
  18. data/examples/relevance/tarantula/html_reporter_example.rb +82 -0
  19. data/examples/relevance/tarantula/invalid_html_handler_example.rb +33 -0
  20. data/examples/relevance/tarantula/io_reporter_example.rb +11 -0
  21. data/examples/relevance/tarantula/link_example.rb +84 -0
  22. data/examples/relevance/tarantula/log_grabber_example.rb +26 -0
  23. data/examples/relevance/tarantula/rails_integration_proxy_example.rb +88 -0
  24. data/examples/relevance/tarantula/result_example.rb +85 -0
  25. data/examples/relevance/tarantula/tidy_handler_example.rb +58 -0
  26. data/examples/relevance/tarantula/transform_example.rb +20 -0
  27. data/examples/relevance/tarantula_example.rb +23 -0
  28. data/laf/images/header_bg.jpg +0 -0
  29. data/laf/images/logo.png +0 -0
  30. data/laf/images/tagline.png +0 -0
  31. data/laf/javascripts/jquery-1.2.3.js +3408 -0
  32. data/laf/javascripts/jquery-ui-tabs.js +890 -0
  33. data/laf/javascripts/jquery.tablesorter.js +861 -0
  34. data/laf/javascripts/tarantula.js +10 -0
  35. data/laf/stylesheets/tarantula.css +346 -0
  36. data/lib/relevance/core_extensions/ellipsize.rb +34 -0
  37. data/lib/relevance/core_extensions/file.rb +9 -0
  38. data/lib/relevance/core_extensions/metaclass.rb +78 -0
  39. data/lib/relevance/core_extensions/response.rb +9 -0
  40. data/lib/relevance/core_extensions/string_chars_fix.rb +11 -0
  41. data/lib/relevance/core_extensions/test_case.rb +19 -0
  42. data/lib/relevance/tarantula.rb +58 -0
  43. data/lib/relevance/tarantula/attack.rb +18 -0
  44. data/lib/relevance/tarantula/attack_handler.rb +37 -0
  45. data/lib/relevance/tarantula/basic_attack.rb +40 -0
  46. data/lib/relevance/tarantula/crawler.rb +254 -0
  47. data/lib/relevance/tarantula/detail.html.erb +81 -0
  48. data/lib/relevance/tarantula/form.rb +23 -0
  49. data/lib/relevance/tarantula/form_submission.rb +88 -0
  50. data/lib/relevance/tarantula/html_document_handler.rb +36 -0
  51. data/lib/relevance/tarantula/html_report_helper.rb +39 -0
  52. data/lib/relevance/tarantula/html_reporter.rb +105 -0
  53. data/lib/relevance/tarantula/index.html.erb +37 -0
  54. data/lib/relevance/tarantula/invalid_html_handler.rb +18 -0
  55. data/lib/relevance/tarantula/io_reporter.rb +34 -0
  56. data/lib/relevance/tarantula/link.rb +94 -0
  57. data/lib/relevance/tarantula/log_grabber.rb +16 -0
  58. data/lib/relevance/tarantula/rails_integration_proxy.rb +68 -0
  59. data/lib/relevance/tarantula/recording.rb +12 -0
  60. data/lib/relevance/tarantula/response.rb +13 -0
  61. data/lib/relevance/tarantula/result.rb +77 -0
  62. data/lib/relevance/tarantula/test_report.html.erb +32 -0
  63. data/lib/relevance/tarantula/tidy_handler.rb +32 -0
  64. data/lib/relevance/tarantula/transform.rb +17 -0
  65. data/lib/relevance/tasks/tarantula_tasks.rake +42 -0
  66. data/lib/tarantula-rails3.rb +9 -0
  67. data/template/tarantula_test.rb +22 -0
  68. metadata +164 -0
data/CHANGELOG ADDED
@@ -0,0 +1,49 @@
1
+ v0.2.0 Implementation of updated look-and-feel [Jason Rudolph]
2
+
3
+ v0.1.8 Add timeouts for crawls to help really long builds [Rob Sanheim]
4
+
5
+ v0.1.7 Minor clean up [Rob Sanheim]
6
+
7
+ v0.1.6
8
+ * add testing for all Rails versions 2.0.2 and up
9
+ * various clean up and housekeeping tasks;
10
+ * start Ruby 1.9 work (but we need Hpricot)
11
+ * show 50 chars of URL, not 30
12
+ * ensure that ActiveRecord gets loaded correctly for the crawler, so that it can rescue RecordNotFound exceptions
13
+ [Rob Sanheim]
14
+
15
+ v0.1.5 Initial implementation of updated look-and-feel [Erik Yowell] [Jason Rudolph]
16
+
17
+ v0.1.4 Bugfix: Include look-and-feel files when building the gem #16 [Jason Rudolph]
18
+
19
+ v0.1.3 Update list of known static file types (e.g., PDFs) to prevent false reports of 404s for links to files that exist in RAILS_ROOT/public [Aaron Bedra]
20
+
21
+ v0.1.2 Remove dependency on Facets gem [Aaron Bedra]
22
+
23
+ v0.1.1 Bugfix: Add ability to handle anchor tags that lack an href attribute #13 [Kevin Gisi]
24
+
25
+ v0.1.0
26
+ * Improve the generated test template to include inline documentation and make the simple case simple [Jason Rudolph]
27
+ * Update README to better serve first-time users [Jason Rudolph]
28
+ * Update development dependencies declarations [Jason Rudolph]
29
+ * Internal refactorings [Aaron Bedra]
30
+ ** Convert test suite to micronaut
31
+ ** Replace Echoe with Jeweler for gem management
32
+ ** Remove unused code
33
+
34
+ v0.0.8.1
35
+ * Fix numerous installation and initial setup issues
36
+ * Enhance rake tasks to support use of Tarantula in a continuous integration environment
37
+ ** Use "rake tarantula:test" to run headless with build-friendly exit codes
38
+ ** Use "rake tarantula:report" to open the Tarantula report in your browser
39
+ * Update README
40
+ ** Provide better installation and setup documentation
41
+ ** Include example of adding a custom attack handler
42
+ * Simplify design to address concerns about hard-to-read fonts
43
+
44
+ v0.0.5
45
+ * Make sure we don't include Relevance::Tarantula into Object - will cause issues with Rails dependencies and is a bad idea in general
46
+ * Update Rakefile for development dependencies
47
+ * Other small clean up tasks
48
+
49
+ v0.0.1 Tarantula becomes a gem. [Aaron Bedra]
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008-2009 Relevance, Inc.
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 deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,161 @@
1
+ = Tarantula
2
+
3
+ == DESCRIPTION
4
+
5
+ Tarantula is a big fuzzy spider. It crawls your Rails application, fuzzing data to see what breaks.
6
+
7
+ == Usage
8
+
9
+ === Installation
10
+
11
+ The latest and greatest version is always available on GitHub. (See the rakefile for dependencies, or
12
+ just let RubyGems handle it.)
13
+
14
+ gem install tarantula
15
+
16
+ You can also grab it from RubyForge, where we will push stable releases but may not be as bleeding edge
17
+ as the GitHub gem.
18
+
19
+ gem install tarantula
20
+
21
+ === Project Setup
22
+
23
+ To set up Tarantula into your application, add the following line into either config/environment.rb or
24
+ config/environments/test.rb (preferred). This assumes that you have Rails 2.1 or higher installed.
25
+
26
+ config.gem 'tarantula', :lib => 'relevance/tarantula'
27
+
28
+ Since Rails doesn't (yet) support automatically loading rake tasks that live inside gems, you will need
29
+ to update your Rakefile to load Tarantula's rake tasks. The simplest approach is to start by vendoring
30
+ Tarantula into your Rails app.
31
+
32
+ mkdir -p vendor/gems
33
+ cd vendor/gems
34
+ gem unpack tarantula
35
+
36
+ You can then add the following line into your Rakefile, which will allow your application to discover
37
+ Tarantula's rake tasks.
38
+
39
+ load File.join(RAILS_ROOT, Dir["vendor/gems/tarantula-*/tasks/*.rake"])
40
+
41
+ === Crawling Your App
42
+
43
+ Use the included rake task to create a Rails integration test that will allow Tarantula to crawl your
44
+ app.
45
+
46
+ #!sh
47
+ rake tarantula:setup
48
+
49
+ Take a moment to familiarize yourself with the generated test. If parts of your application require
50
+ login, update the test to make sure Tarantula can access those parts of your app.
51
+
52
+ require "relevance/tarantula"
53
+
54
+ class TarantulaTest < ActionController::IntegrationTest
55
+ # Load enough test data to ensure that there's a link to every page in your
56
+ # application. Doing so allows Tarantula to follow those links and crawl
57
+ # every page. For many applications, you can load a decent data set by
58
+ # loading all fixtures.
59
+ fixtures :all
60
+
61
+ def test_tarantula
62
+ # If your application requires users to log in before accessing certain
63
+ # pages, uncomment the lines below and update them to allow this test to
64
+ # log in to your application. Doing so allows Tarantula to crawl the
65
+ # pages that are only accessible to logged-in users.
66
+ #
67
+ # post '/session', :login => 'quentin', :password => 'monkey'
68
+ # follow_redirect!
69
+
70
+ tarantula_crawl(self)
71
+ end
72
+ end
73
+
74
+ If you want to set custom options, you can get access to the crawler and set properties before running
75
+ it. For example, this would turn on HTMLTidy.
76
+
77
+ def test_tarantula
78
+ post '/session', :login => 'kilgore', :password => 'trout'
79
+ assert_response :redirect
80
+ assert_redirected_to '/'
81
+ follow_redirect!
82
+
83
+ t = tarantula_crawler(self)
84
+ t.handlers << Relevance::Tarantula::TidyHandler.new
85
+ t.crawl '/'
86
+ end
87
+
88
+ Now it's time to turn Tarantula loose on your app. Assuming your project is at /work/project/:
89
+
90
+ #!sh
91
+ cd /work/project
92
+ rake tarantula:test
93
+
94
+ == Verbose Mode
95
+
96
+ If you run the test using the steps shown above, Tarantula will produce a report in tmp/tarantula. You
97
+ can also set VERBOSE=true to see more detail as the test runs.
98
+
99
+ For more options, please see the test suite.
100
+
101
+ == Allowed Errors
102
+
103
+ If, for example, a 404 is an appropriate response for some URLs, you can tell Tarantula to allow 404s
104
+ for URLs matching a given regex:
105
+
106
+ t = tarantula_crawler(self)
107
+ t.allow_404_for %r{/users/\d+/}
108
+
109
+ == Testing for Common Attacks
110
+
111
+ You can specify the attack strings that Tarantula throws at your application.
112
+
113
+ def test_tarantula
114
+ t = tarantula_crawler(self)
115
+
116
+ Relevance::Tarantula::FormSubmission.attacks << {
117
+ :name => :xss,
118
+ :input => "<script>gotcha!</script>",
119
+ :output => "<script>gotcha!</script>",
120
+ }
121
+
122
+ Relevance::Tarantula::FormSubmission.attacks << {
123
+ :name => :sql_injection,
124
+ :input => "a'; DROP TABLE posts;",
125
+ }
126
+
127
+ t.handlers << Relevance::Tarantula::AttackHandler.new
128
+ t.times_to_crawl = 2
129
+ t.crawl "/posts"
130
+ end
131
+
132
+ This example adds custom attacks for both SQL injection and XSS. It also tells Tarantula to crawl the
133
+ app 2 times. This is important for XSS attacks because the results won't appear until the second time
134
+ Tarantula performs the crawl.
135
+
136
+ == Timeout
137
+
138
+ You can specify a timeout for each specific crawl that Tarantula runs. For example:
139
+
140
+ def test_tarantula
141
+ t = tarantula_crawler(self)
142
+ t.times_to_crawl = 2
143
+ t.crawl_timeout = 5.minutes
144
+ t.crawl "/"
145
+ end
146
+
147
+ The above will crawl your app twice, and each specific crawl will timeout if it takes longer then 5 minutes. You may need a timeout to keep the tarantula test time reasonable if your app is large or just happens to have a large amount of 'never-ending' links, such as with an any sort of "auto-admin" interface.
148
+
149
+ == Bugs/Requests
150
+
151
+ Please submit your bug reports, patches, or feature requests at Lighthouse:
152
+
153
+ http://relevance.lighthouseapp.com/projects/17868-tarantula/overview
154
+
155
+ You can view the continuous integration results for Tarantula, including results against all supported versions of Rails, on RunCodeRun here:
156
+
157
+ http://runcoderun.com/relevance/tarantula
158
+
159
+ == License
160
+
161
+ Tarantula is released under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,83 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'micronaut'
5
+ require 'micronaut/rake_task'
6
+
7
+ begin
8
+ require 'jeweler'
9
+ files = ["CHANGELOG", "MIT-LICENSE", "Rakefile", "README.rdoc", "VERSION.yml"]
10
+ files << Dir["examples/**/*", "laf/**/*", "lib/**/*", "tasks/**/*", "template/**/*"]
11
+
12
+ Jeweler::Tasks.new do |s|
13
+ s.name = "tarantula"
14
+ s.summary = "A big hairy fuzzy spider that crawls your site, wreaking havoc"
15
+ s.description = "A big hairy fuzzy spider that crawls your site, wreaking havoc"
16
+ s.homepage = "http://github.com/relevance/tarantula"
17
+ s.email = "opensource@thinkrelevance.com"
18
+ s.authors = ["Relevance, Inc."]
19
+ s.require_paths = ["lib"]
20
+ s.files = files.flatten
21
+ s.add_dependency 'htmlentities', '>= 4.2.0'
22
+ s.add_dependency 'hpricot', '>= 0.8.1'
23
+ s.add_development_dependency 'micronaut'
24
+ s.add_development_dependency 'log_buddy'
25
+ end
26
+ Jeweler::GemcutterTasks.new
27
+ rescue LoadError
28
+ puts "Jeweler not available. Install it with: gem install jeweler"
29
+ end
30
+
31
+ desc "Run all micronaut examples"
32
+ Micronaut::RakeTask.new :examples do |t|
33
+ t.pattern = "examples/**/*_example.rb"
34
+ end
35
+
36
+ desc "Run all micronaut examples using rcov"
37
+ Micronaut::RakeTask.new :rcov do |t|
38
+ t.pattern = "examples/**/*_example.rb"
39
+ t.rcov = true
40
+ t.rcov_opts = %[--exclude "gems/*,/Library/Ruby/*,config/*" --text-summary --sort coverage]
41
+ end
42
+
43
+ namespace :examples do
44
+
45
+ RAILS_VERSIONS = %w[2.3.2 2.3.4]
46
+
47
+ unless RUBY_VERSION =~ /^1\.9\./
48
+ RAILS_VERSIONS.unshift(*%w[2.0.2 2.1.0 2.1.1 2.2.2 2.3.3])
49
+ RAILS_VERSIONS.sort!
50
+ end
51
+
52
+ desc "Run examples with multiple versions of rails"
53
+ task :multi_rails do
54
+ RAILS_VERSIONS.each do |rails_version|
55
+ puts
56
+ sh "RAILS_VERSION='#{rails_version}' rake examples"
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ if ENV["RUN_CODE_RUN"]
63
+ task :default => [:check_dependencies, "examples:multi_rails"]
64
+ else
65
+ task :default => [:check_dependencies, :examples]
66
+ end
67
+
68
+ begin
69
+ %w{sdoc sdoc-helpers rdiscount}.each { |name| gem name }
70
+ require 'sdoc_helpers'
71
+ rescue LoadError => ex
72
+ puts "sdoc support not enabled:"
73
+ puts ex.inspect
74
+ end
75
+
76
+ require 'rake/rdoctask'
77
+ Rake::RDocTask.new do |rdoc|
78
+ version = File.exist?('VERSION') ? File.read('VERSION') : ''
79
+ rdoc.rdoc_dir = 'rdoc'
80
+ rdoc.title = "tarantula #{version}"
81
+ rdoc.rdoc_files.include('README*')
82
+ rdoc.rdoc_files.include('lib/**/*.rb')
83
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 3
4
+ :patch: 3
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ lib_path = File.expand_path(File.dirname(__FILE__) + "/../lib")
3
+ $LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
4
+ require 'rubygems'
5
+ gem "micronaut", ">= 0.2.4"
6
+ gem "log_buddy"
7
+ gem "mocha"
8
+ if rails_version = ENV['RAILS_VERSION']
9
+ gem "rails", rails_version
10
+ end
11
+ require "rails/version"
12
+ if Rails::VERSION::STRING < "2.3.1" && RUBY_VERSION >= "1.9.1"
13
+ puts "Tarantula requires Rails 2.3.1 or higher for Ruby 1.9 support"
14
+ exit(1)
15
+ end
16
+ puts "==== Testing with Rails #{Rails::VERSION::STRING} ===="
17
+ gem 'actionpack'
18
+ gem 'activerecord'
19
+ gem 'activesupport'
20
+
21
+ require 'ostruct'
22
+ require 'active_support'
23
+ require 'action_controller'
24
+ require 'active_record'
25
+ require 'relevance/tarantula'
26
+ require 'micronaut'
27
+ require 'mocha'
28
+
29
+ def test_output_dir
30
+ File.join(File.dirname(__FILE__), "..", "tmp", "test_output")
31
+ end
32
+
33
+ # TODO change puts/print to use a single method for logging, which will then make the stubbing cleaner
34
+ def stub_puts_and_print(obj)
35
+ obj.stubs(:puts)
36
+ obj.stubs(:print)
37
+ end
38
+
39
+ def make_link(link, crawler=Relevance::Tarantula::Crawler.new, referrer=nil)
40
+ Relevance::Tarantula::Link.new(link, crawler, referrer)
41
+ end
42
+
43
+ def make_form(form, crawler=Relevance::Tarantula::Crawler.new, referrer=nil)
44
+ Relevance::Tarantula::Form.new(form, crawler, referrer)
45
+ end
46
+
47
+ def not_in_editor?
48
+ ['TM_MODE', 'EMACS', 'VIM'].all? { |k| !ENV.has_key?(k) }
49
+ end
50
+
51
+ Micronaut.configure do |c|
52
+ c.alias_example_to :fit, :focused => true
53
+ c.alias_example_to :xit, :disabled => true
54
+ c.mock_with :mocha
55
+ c.color_enabled = not_in_editor?
56
+ c.filter_run :focused => true
57
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "../..", "example_helper.rb"))
2
+
3
+ describe "Relevance::CoreExtensions::Object#ellipsize" do
4
+ it "converts nil to empty string" do
5
+ nil.ellipsize.should == ""
6
+ end
7
+
8
+ it "doesn't touch short strings" do
9
+ "hello".ellipsize.should == "hello"
10
+ end
11
+
12
+ it "calls inspect on non-strings" do
13
+ [1,2,3].ellipsize.should == "[1, 2, 3]"
14
+ end
15
+
16
+ it "shortens long strings and adds ..." do
17
+ "long-string".ellipsize(5).should == "long-..."
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "../..", "example_helper.rb"))
2
+ require 'relevance/core_extensions/file'
3
+
4
+ describe "Relevance::CoreExtensions::File#extension" do
5
+ it "should return the extension without the leading dot" do
6
+ File.extension("foo.bar").should == "bar"
7
+ end
8
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "../..", "example_helper.rb"))
2
+ require 'relevance/core_extensions/file'
3
+
4
+ describe "Relevance::CoreExtensions::Response#html?" do
5
+ before do
6
+ @response = OpenStruct.new
7
+ @response.extend(Relevance::CoreExtensions::Response)
8
+ end
9
+
10
+ it "should be html if the content-type is 'text/html'" do
11
+ @response.content_type = "text/html"
12
+ @response.should be_html
13
+ @response.content_type = "text/html;charset=iso-8859-2"
14
+ @response.should be_html
15
+ end
16
+
17
+ it "should not be html if the content-type isn't an html type" do
18
+ @response.content_type = "text/plain"
19
+ @response.should_not be_html
20
+ end
21
+
22
+ # better ideas welcome, but be careful not to
23
+ # castrate tarantula for proxies that don't set the content-type
24
+ it "should pretend we have html if the content-type is nil" do
25
+ @response.content_type = nil
26
+ @response.should be_html
27
+ end
28
+
29
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "../..", "example_helper.rb"))
2
+ require 'relevance/core_extensions/test_case'
3
+
4
+ describe "TestCase extensions" do
5
+ pending "can create the crawler" do
6
+ Relevance::Tarantula::RailsIntegrationProxy.stubs(:rails_root).returns("STUB_RAILS_ROOT")
7
+ Relevance::Tarantula::Crawler.any_instance.stubs(:rails_root).returns("STUB_RAILS_ROOT")
8
+ tarantula_crawler(stub_everything)
9
+ end
10
+
11
+ pending "can crawl" do
12
+ (crawler = mock).expects(:crawl).with("/foo")
13
+ expects(:tarantula_crawler).returns(crawler)
14
+ tarantula_crawl(:integration_test_stub, :url => "/foo")
15
+ end
16
+
17
+ it "should get mixed into ActionController::IntegrationTest" do
18
+ ActionController::IntegrationTest.ancestors.should include(Relevance::CoreExtensions::TestCaseExtensions)
19
+ end
20
+ end