summary refs log tree commit
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2022-02-03 13:20:12 -0800
committerJeremy Evans <code@jeremyevans.net>2022-02-03 16:35:50 -0800
commit2833813bd7f2a1872831d83cc9a0bb60f7d94fdd (patch)
tree74c1cb61a6e6fe4810f24ba795744f1ec693719e
parent568dee5a2de80a9da20e2baf084b215abeee4ea8 (diff)
downloadrack-2833813bd7f2a1872831d83cc9a0bb60f7d94fdd.tar.gz
Enable directly requiring Rack components
Add test:separate task to test run each test file separately.
This is to test that directly requiring a rack component will work.

With test:separate, the test helper will not require rack, and each
test file should call separate_testing with a block that uses
require_relative to only require that component being tested.

Add the appropriate relative requires to get all tests passing
when run separately.

Note that this isn't foolproof. In many cases, the tests use
Rack components that are not under test (such as lint and mock),
and both of those other other rack components, so it's possible
the tests are loading hidden dependencies.  I attempted to check
each component to try to find the hidden dependencies, but it is
certainly possible I missed something.

Implements #1621.
-rw-r--r--Rakefile18
-rw-r--r--lib/rack.rb59
-rw-r--r--lib/rack/auth/abstract/handler.rb2
-rw-r--r--lib/rack/auth/abstract/request.rb2
-rw-r--r--lib/rack/builder.rb2
-rw-r--r--lib/rack/cascade.rb2
-rw-r--r--lib/rack/chunked.rb3
-rw-r--r--lib/rack/common_logger.rb4
-rw-r--r--lib/rack/conditional_get.rb4
-rw-r--r--lib/rack/constants.rb61
-rw-r--r--lib/rack/content_length.rb3
-rw-r--r--lib/rack/content_type.rb3
-rw-r--r--lib/rack/deflater.rb5
-rw-r--r--lib/rack/directory.rb6
-rw-r--r--lib/rack/etag.rb4
-rw-r--r--lib/rack/events.rb4
-rw-r--r--lib/rack/files.rb6
-rw-r--r--lib/rack/handler/webrick.rb3
-rw-r--r--lib/rack/head.rb3
-rwxr-xr-xlib/rack/lint.rb3
-rw-r--r--lib/rack/lobster.rb8
-rw-r--r--lib/rack/lock.rb2
-rw-r--r--lib/rack/logger.rb2
-rw-r--r--lib/rack/method_override.rb4
-rw-r--r--lib/rack/mock.rb5
-rw-r--r--lib/rack/multipart.rb6
-rw-r--r--lib/rack/multipart/generator.rb2
-rw-r--r--lib/rack/multipart/parser.rb4
-rw-r--r--lib/rack/multipart/uploaded_file.rb4
-rw-r--r--lib/rack/null_logger.rb2
-rw-r--r--lib/rack/recursive.rb2
-rw-r--r--lib/rack/request.rb6
-rw-r--r--lib/rack/response.rb4
-rw-r--r--lib/rack/runtime.rb2
-rw-r--r--lib/rack/sendfile.rb4
-rw-r--r--lib/rack/server.rb9
-rw-r--r--lib/rack/session/abstract/id.rb5
-rw-r--r--lib/rack/session/cookie.rb5
-rw-r--r--lib/rack/session/pool.rb1
-rw-r--r--lib/rack/show_exceptions.rb4
-rw-r--r--lib/rack/show_status.rb5
-rw-r--r--lib/rack/static.rb4
-rw-r--r--lib/rack/tempfile_reaper.rb3
-rw-r--r--lib/rack/urlmap.rb2
-rw-r--r--lib/rack/utils.rb1
-rw-r--r--test/helper.rb11
-rw-r--r--test/psych_fix.rb8
-rw-r--r--test/spec_auth_basic.rb6
-rw-r--r--test/spec_auth_digest.rb10
-rw-r--r--test/spec_body_proxy.rb4
-rw-r--r--test/spec_builder.rb9
-rw-r--r--test/spec_cascade.rb8
-rw-r--r--test/spec_chunked.rb6
-rw-r--r--test/spec_common_logger.rb6
-rw-r--r--test/spec_conditional_get.rb6
-rw-r--r--test/spec_config.rb7
-rw-r--r--test/spec_content_length.rb6
-rw-r--r--test/spec_content_type.rb6
-rw-r--r--test/spec_deflater.rb6
-rw-r--r--test/spec_directory.rb8
-rw-r--r--test/spec_etag.rb6
-rw-r--r--test/spec_events.rb4
-rw-r--r--test/spec_files.rb6
-rw-r--r--test/spec_handler.rb4
-rw-r--r--test/spec_head.rb6
-rwxr-xr-xtest/spec_lint.rb5
-rw-r--r--test/spec_lobster.rb7
-rw-r--r--test/spec_lock.rb6
-rw-r--r--test/spec_logger.rb6
-rw-r--r--test/spec_media_type.rb4
-rw-r--r--test/spec_method_override.rb6
-rw-r--r--test/spec_mime.rb4
-rw-r--r--test/spec_mock.rb18
-rw-r--r--test/spec_multipart.rb8
-rw-r--r--test/spec_null_logger.rb6
-rw-r--r--test/spec_recursive.rb7
-rw-r--r--test/spec_request.rb6
-rw-r--r--test/spec_response.rb4
-rw-r--r--test/spec_rewindable_input.rb4
-rw-r--r--test/spec_runtime.rb6
-rw-r--r--test/spec_sendfile.rb6
-rw-r--r--test/spec_server.rb10
-rw-r--r--test/spec_session_abstract_id.rb5
-rw-r--r--test/spec_session_abstract_persisted.rb6
-rw-r--r--test/spec_session_abstract_persisted_secure_secure_session_hash.rb6
-rw-r--r--test/spec_session_abstract_session_hash.rb4
-rw-r--r--test/spec_session_cookie.rb7
-rw-r--r--test/spec_session_pool.rb8
-rw-r--r--test/spec_show_exceptions.rb6
-rw-r--r--test/spec_show_status.rb6
-rw-r--r--test/spec_static.rb6
-rw-r--r--test/spec_tempfile_reaper.rb6
-rw-r--r--test/spec_urlmap.rb6
-rw-r--r--test/spec_utils.rb8
-rw-r--r--test/spec_version.rb4
-rw-r--r--test/spec_webrick.rb7
-rw-r--r--test/test_request.rb1
97 files changed, 545 insertions, 80 deletions
diff --git a/Rakefile b/Rakefile
index 88cf6621..7848b0c0 100644
--- a/Rakefile
+++ b/Rakefile
@@ -98,8 +98,24 @@ task "test_cov" do
   Rake::Task['test:regular'].invoke
 end
 
+desc "Run separate tests for each test file, to test directly requiring components"
+task "test:separate" do
+  fails = []
+  FileList["test/**/spec_*.rb"].each do |file|
+    puts "#{FileUtils::RUBY} -w #{file}"
+    fails << file unless system({'SEPARATE'=>'1'},  FileUtils::RUBY, '-w', file)
+  end
+  if fails.empty?
+    puts 'All test files passed'
+  else
+    puts "Failures in the following test files:"
+    puts fails
+    raise "At least one separate test failed"
+  end
+end
+
 desc "Run all the fast + platform agnostic tests"
-task test: %w[spec test:regular]
+task test: %w[spec test:regular test:separate]
 
 desc "Run all the tests we run on CI"
 task ci: :test
diff --git a/lib/rack.rb b/lib/rack.rb
index ad3efec6..f64a71a9 100644
--- a/lib/rack.rb
+++ b/lib/rack.rb
@@ -12,66 +12,9 @@
 # so it should be enough just to <tt>require 'rack'</tt> in your code.
 
 require_relative 'rack/version'
+require_relative 'rack/constants'
 
 module Rack
-  HTTP_HOST         = 'HTTP_HOST'
-  HTTP_PORT         = 'HTTP_PORT'
-  HTTPS             = 'HTTPS'
-  PATH_INFO         = 'PATH_INFO'
-  REQUEST_METHOD    = 'REQUEST_METHOD'
-  REQUEST_PATH      = 'REQUEST_PATH'
-  SCRIPT_NAME       = 'SCRIPT_NAME'
-  QUERY_STRING      = 'QUERY_STRING'
-  SERVER_PROTOCOL   = 'SERVER_PROTOCOL'
-  SERVER_NAME       = 'SERVER_NAME'
-  SERVER_PORT       = 'SERVER_PORT'
-  CACHE_CONTROL     = 'Cache-Control'
-  EXPIRES           = 'Expires'
-  CONTENT_LENGTH    = 'Content-Length'
-  CONTENT_TYPE      = 'Content-Type'
-  SET_COOKIE        = 'Set-Cookie'
-  TRANSFER_ENCODING = 'Transfer-Encoding'
-  HTTP_COOKIE       = 'HTTP_COOKIE'
-  ETAG              = 'ETag'
-
-  # HTTP method verbs
-  GET     = 'GET'
-  POST    = 'POST'
-  PUT     = 'PUT'
-  PATCH   = 'PATCH'
-  DELETE  = 'DELETE'
-  HEAD    = 'HEAD'
-  OPTIONS = 'OPTIONS'
-  LINK    = 'LINK'
-  UNLINK  = 'UNLINK'
-  TRACE   = 'TRACE'
-
-  # Rack environment variables
-  RACK_VERSION                        = 'rack.version'
-  RACK_TEMPFILES                      = 'rack.tempfiles'
-  RACK_ERRORS                         = 'rack.errors'
-  RACK_LOGGER                         = 'rack.logger'
-  RACK_INPUT                          = 'rack.input'
-  RACK_SESSION                        = 'rack.session'
-  RACK_SESSION_OPTIONS                = 'rack.session.options'
-  RACK_SHOWSTATUS_DETAIL              = 'rack.showstatus.detail'
-  RACK_URL_SCHEME                     = 'rack.url_scheme'
-  RACK_HIJACK                         = 'rack.hijack'
-  RACK_IS_HIJACK                      = 'rack.hijack?'
-  RACK_HIJACK_IO                      = 'rack.hijack_io'
-  RACK_RECURSIVE_INCLUDE              = 'rack.recursive.include'
-  RACK_MULTIPART_BUFFER_SIZE          = 'rack.multipart.buffer_size'
-  RACK_MULTIPART_TEMPFILE_FACTORY     = 'rack.multipart.tempfile_factory'
-  RACK_REQUEST_FORM_INPUT             = 'rack.request.form_input'
-  RACK_REQUEST_FORM_HASH              = 'rack.request.form_hash'
-  RACK_REQUEST_FORM_VARS              = 'rack.request.form_vars'
-  RACK_REQUEST_COOKIE_HASH            = 'rack.request.cookie_hash'
-  RACK_REQUEST_COOKIE_STRING          = 'rack.request.cookie_string'
-  RACK_REQUEST_QUERY_HASH             = 'rack.request.query_hash'
-  RACK_REQUEST_QUERY_STRING           = 'rack.request.query_string'
-  RACK_METHODOVERRIDE_ORIGINAL_METHOD = 'rack.methodoverride.original_method'
-  RACK_SESSION_UNPACKED_COOKIE_DATA   = 'rack.session.unpacked_cookie_data'
-
   autoload :Builder, "rack/builder"
   autoload :BodyProxy, "rack/body_proxy"
   autoload :Cascade, "rack/cascade"
diff --git a/lib/rack/auth/abstract/handler.rb b/lib/rack/auth/abstract/handler.rb
index 3ed87091..8a963dab 100644
--- a/lib/rack/auth/abstract/handler.rb
+++ b/lib/rack/auth/abstract/handler.rb
@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require_relative '../../constants'
+
 module Rack
   module Auth
     # Rack::Auth::AbstractHandler implements common authentication functionality.
diff --git a/lib/rack/auth/abstract/request.rb b/lib/rack/auth/abstract/request.rb
index 7b499f1b..f8723315 100644
--- a/lib/rack/auth/abstract/request.rb
+++ b/lib/rack/auth/abstract/request.rb
@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require_relative '../../request'
+
 module Rack
   module Auth
     class AbstractRequest
diff --git a/lib/rack/builder.rb b/lib/rack/builder.rb
index 3dcecb55..9ef656c1 100644
--- a/lib/rack/builder.rb
+++ b/lib/rack/builder.rb
@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require_relative 'urlmap'
+
 module Rack
   # Rack::Builder implements a small DSL to iteratively construct Rack
   # applications.
diff --git a/lib/rack/cascade.rb b/lib/rack/cascade.rb
index d71274c2..027d7e40 100644
--- a/lib/rack/cascade.rb
+++ b/lib/rack/cascade.rb
@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+
 module Rack
   # Rack::Cascade tries a request on several apps, and returns the
   # first response that is not 404 or 405 (or in a list of configured
diff --git a/lib/rack/chunked.rb b/lib/rack/chunked.rb
index 84c66001..f880dd85 100644
--- a/lib/rack/chunked.rb
+++ b/lib/rack/chunked.rb
@@ -1,5 +1,8 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+require_relative 'utils'
+
 module Rack
 
   # Middleware that applies chunked transfer encoding to response bodies
diff --git a/lib/rack/common_logger.rb b/lib/rack/common_logger.rb
index 4acd11ff..30456e50 100644
--- a/lib/rack/common_logger.rb
+++ b/lib/rack/common_logger.rb
@@ -1,5 +1,9 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+require_relative 'utils'
+require_relative 'body_proxy'
+
 module Rack
   # Rack::CommonLogger forwards every request to the given +app+, and
   # logs a line in the
diff --git a/lib/rack/conditional_get.rb b/lib/rack/conditional_get.rb
index 7b7808ac..d56f1454 100644
--- a/lib/rack/conditional_get.rb
+++ b/lib/rack/conditional_get.rb
@@ -1,5 +1,9 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+require_relative 'utils'
+require_relative 'body_proxy'
+
 module Rack
 
   # Middleware that enables conditional GET using If-None-Match and
diff --git a/lib/rack/constants.rb b/lib/rack/constants.rb
new file mode 100644
index 00000000..55cfd9fe
--- /dev/null
+++ b/lib/rack/constants.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Rack
+  HTTP_HOST         = 'HTTP_HOST'
+  HTTP_PORT         = 'HTTP_PORT'
+  HTTPS             = 'HTTPS'
+  PATH_INFO         = 'PATH_INFO'
+  REQUEST_METHOD    = 'REQUEST_METHOD'
+  REQUEST_PATH      = 'REQUEST_PATH'
+  SCRIPT_NAME       = 'SCRIPT_NAME'
+  QUERY_STRING      = 'QUERY_STRING'
+  SERVER_PROTOCOL   = 'SERVER_PROTOCOL'
+  SERVER_NAME       = 'SERVER_NAME'
+  SERVER_PORT       = 'SERVER_PORT'
+  CACHE_CONTROL     = 'Cache-Control'
+  EXPIRES           = 'Expires'
+  CONTENT_LENGTH    = 'Content-Length'
+  CONTENT_TYPE      = 'Content-Type'
+  SET_COOKIE        = 'Set-Cookie'
+  TRANSFER_ENCODING = 'Transfer-Encoding'
+  HTTP_COOKIE       = 'HTTP_COOKIE'
+  ETAG              = 'ETag'
+
+  # HTTP method verbs
+  GET     = 'GET'
+  POST    = 'POST'
+  PUT     = 'PUT'
+  PATCH   = 'PATCH'
+  DELETE  = 'DELETE'
+  HEAD    = 'HEAD'
+  OPTIONS = 'OPTIONS'
+  LINK    = 'LINK'
+  UNLINK  = 'UNLINK'
+  TRACE   = 'TRACE'
+
+  # Rack environment variables
+  RACK_VERSION                        = 'rack.version'
+  RACK_TEMPFILES                      = 'rack.tempfiles'
+  RACK_ERRORS                         = 'rack.errors'
+  RACK_LOGGER                         = 'rack.logger'
+  RACK_INPUT                          = 'rack.input'
+  RACK_SESSION                        = 'rack.session'
+  RACK_SESSION_OPTIONS                = 'rack.session.options'
+  RACK_SHOWSTATUS_DETAIL              = 'rack.showstatus.detail'
+  RACK_URL_SCHEME                     = 'rack.url_scheme'
+  RACK_HIJACK                         = 'rack.hijack'
+  RACK_IS_HIJACK                      = 'rack.hijack?'
+  RACK_HIJACK_IO                      = 'rack.hijack_io'
+  RACK_RECURSIVE_INCLUDE              = 'rack.recursive.include'
+  RACK_MULTIPART_BUFFER_SIZE          = 'rack.multipart.buffer_size'
+  RACK_MULTIPART_TEMPFILE_FACTORY     = 'rack.multipart.tempfile_factory'
+  RACK_REQUEST_FORM_INPUT             = 'rack.request.form_input'
+  RACK_REQUEST_FORM_HASH              = 'rack.request.form_hash'
+  RACK_REQUEST_FORM_VARS              = 'rack.request.form_vars'
+  RACK_REQUEST_COOKIE_HASH            = 'rack.request.cookie_hash'
+  RACK_REQUEST_COOKIE_STRING          = 'rack.request.cookie_string'
+  RACK_REQUEST_QUERY_HASH             = 'rack.request.query_hash'
+  RACK_REQUEST_QUERY_STRING           = 'rack.request.query_string'
+  RACK_METHODOVERRIDE_ORIGINAL_METHOD = 'rack.methodoverride.original_method'
+  RACK_SESSION_UNPACKED_COOKIE_DATA   = 'rack.session.unpacked_cookie_data'
+end
diff --git a/lib/rack/content_length.rb b/lib/rack/content_length.rb
index 48e91cfc..b82707dd 100644
--- a/lib/rack/content_length.rb
+++ b/lib/rack/content_length.rb
@@ -1,5 +1,8 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+require_relative 'utils'
+
 module Rack
 
   # Sets the Content-Length header on responses that do not specify
diff --git a/lib/rack/content_type.rb b/lib/rack/content_type.rb
index 503f7070..e37011b9 100644
--- a/lib/rack/content_type.rb
+++ b/lib/rack/content_type.rb
@@ -1,5 +1,8 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+require_relative 'utils'
+
 module Rack
 
   # Sets the Content-Type header on responses which don't have one.
diff --git a/lib/rack/deflater.rb b/lib/rack/deflater.rb
index a8d418a6..372ad615 100644
--- a/lib/rack/deflater.rb
+++ b/lib/rack/deflater.rb
@@ -3,6 +3,11 @@
 require "zlib"
 require "time"  # for Time.httpdate
 
+require_relative 'constants'
+require_relative 'utils'
+require_relative 'request'
+require_relative 'body_proxy'
+
 module Rack
   # This middleware enables content encoding of http responses,
   # usually for purposes of compression.
diff --git a/lib/rack/directory.rb b/lib/rack/directory.rb
index be72be01..ebc131e9 100644
--- a/lib/rack/directory.rb
+++ b/lib/rack/directory.rb
@@ -2,6 +2,12 @@
 
 require 'time'
 
+require_relative 'constants'
+require_relative 'utils'
+require_relative 'head'
+require_relative 'mime'
+require_relative 'files'
+
 module Rack
   # Rack::Directory serves entries below the +root+ given, according to the
   # path info of the Rack request. If a directory is found, the file's contents
diff --git a/lib/rack/etag.rb b/lib/rack/etag.rb
index 4717c2c4..c5626f70 100644
--- a/lib/rack/etag.rb
+++ b/lib/rack/etag.rb
@@ -1,8 +1,10 @@
 # frozen_string_literal: true
 
-require_relative '../rack'
 require 'digest/sha2'
 
+require_relative 'constants'
+require_relative 'utils'
+
 module Rack
   # Automatically sets the ETag header on all String bodies.
   #
diff --git a/lib/rack/events.rb b/lib/rack/events.rb
index 65055fdc..c7bb201f 100644
--- a/lib/rack/events.rb
+++ b/lib/rack/events.rb
@@ -1,5 +1,9 @@
 # frozen_string_literal: true
 
+require_relative 'body_proxy'
+require_relative 'request'
+require_relative 'response'
+
 module Rack
   ### This middleware provides hooks to certain places in the request /
   # response lifecycle.  This is so that middleware that don't need to filter
diff --git a/lib/rack/files.rb b/lib/rack/files.rb
index e745eb39..c7810e40 100644
--- a/lib/rack/files.rb
+++ b/lib/rack/files.rb
@@ -2,6 +2,12 @@
 
 require 'time'
 
+require_relative 'constants'
+require_relative 'head'
+require_relative 'utils'
+require_relative 'request'
+require_relative 'mime'
+
 module Rack
   # Rack::Files serves files below the +root+ directory given, according to the
   # path info of the Rack request.
diff --git a/lib/rack/handler/webrick.rb b/lib/rack/handler/webrick.rb
index 9ce73b40..a96587e2 100644
--- a/lib/rack/handler/webrick.rb
+++ b/lib/rack/handler/webrick.rb
@@ -3,6 +3,9 @@
 require 'webrick'
 require 'stringio'
 
+require_relative '../constants'
+require_relative '../version'
+
 # This monkey patch allows for applications to perform their own chunking
 # through WEBrick::HTTPResponse if rack is set to true.
 class WEBrick::HTTPResponse
diff --git a/lib/rack/head.rb b/lib/rack/head.rb
index 8025a27d..3bd9a75b 100644
--- a/lib/rack/head.rb
+++ b/lib/rack/head.rb
@@ -1,5 +1,8 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+require_relative 'body_proxy'
+
 module Rack
   # Rack::Head returns an empty body for all HEAD requests. It leaves
   # all other requests unchanged.
diff --git a/lib/rack/lint.rb b/lib/rack/lint.rb
index fe616138..9f4ab065 100755
--- a/lib/rack/lint.rb
+++ b/lib/rack/lint.rb
@@ -2,6 +2,9 @@
 
 require 'forwardable'
 
+require_relative 'constants'
+require_relative 'utils'
+
 module Rack
   # Rack::Lint validates your application and the requests and
   # responses according to the Rack spec.
diff --git a/lib/rack/lobster.rb b/lib/rack/lobster.rb
index b86a625d..ede7f909 100644
--- a/lib/rack/lobster.rb
+++ b/lib/rack/lobster.rb
@@ -2,6 +2,10 @@
 
 require 'zlib'
 
+require_relative 'constants'
+require_relative 'request'
+require_relative 'response'
+
 module Rack
   # Paste has a Pony, Rack has a Lobster!
   class Lobster
@@ -62,7 +66,9 @@ end
 
 if $0 == __FILE__
   # :nocov:
-  require_relative '../rack'
+  require_relative 'server'
+  require_relative 'show_exceptions'
+  require_relative 'lint'
   Rack::Server.start(
     app: Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), Port: 9292
   )
diff --git a/lib/rack/lock.rb b/lib/rack/lock.rb
index 3b084c28..342123a0 100644
--- a/lib/rack/lock.rb
+++ b/lib/rack/lock.rb
@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require_relative 'body_proxy'
+
 module Rack
   # Rack::Lock locks every request inside a mutex, so that every request
   # will effectively be executed synchronously.
diff --git a/lib/rack/logger.rb b/lib/rack/logger.rb
index 6c4bede0..bdcc0690 100644
--- a/lib/rack/logger.rb
+++ b/lib/rack/logger.rb
@@ -2,6 +2,8 @@
 
 require 'logger'
 
+require_relative 'constants'
+
 module Rack
   # Sets up rack.logger to write to rack.errors stream
   class Logger
diff --git a/lib/rack/method_override.rb b/lib/rack/method_override.rb
index 453901fc..cf7fcf75 100644
--- a/lib/rack/method_override.rb
+++ b/lib/rack/method_override.rb
@@ -1,5 +1,9 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+require_relative 'request'
+require_relative 'utils'
+
 module Rack
   class MethodOverride
     HTTP_METHODS = %w[GET HEAD PUT POST DELETE OPTIONS PATCH LINK UNLINK]
diff --git a/lib/rack/mock.rb b/lib/rack/mock.rb
index c4f39b63..c0f348bb 100644
--- a/lib/rack/mock.rb
+++ b/lib/rack/mock.rb
@@ -2,10 +2,13 @@
 
 require 'uri'
 require 'stringio'
-require_relative '../rack'
 require 'cgi/cookie'
 require 'time'
 
+require_relative 'response'
+require_relative 'version'
+require_relative 'constants'
+
 module Rack
   # Rack::MockRequest helps testing your Rack application without
   # actually using HTTP.
diff --git a/lib/rack/multipart.rb b/lib/rack/multipart.rb
index 45f43bb6..9c2887e5 100644
--- a/lib/rack/multipart.rb
+++ b/lib/rack/multipart.rb
@@ -1,6 +1,7 @@
 # frozen_string_literal: true
 
-require_relative 'multipart/parser'
+require_relative 'constants'
+require_relative 'utils'
 
 module Rack
   # A multipart form data parser, adapted from IOWA.
@@ -63,3 +64,6 @@ module Rack
 
   end
 end
+
+require_relative 'request' unless defined?(Rack::Request)
+require_relative 'multipart/parser'
diff --git a/lib/rack/multipart/generator.rb b/lib/rack/multipart/generator.rb
index 8ba1a578..8edb3d6a 100644
--- a/lib/rack/multipart/generator.rb
+++ b/lib/rack/multipart/generator.rb
@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require_relative '../multipart'
+
 module Rack
   module Multipart
     class Generator
diff --git a/lib/rack/multipart/parser.rb b/lib/rack/multipart/parser.rb
index 3a6e0717..ce50e03e 100644
--- a/lib/rack/multipart/parser.rb
+++ b/lib/rack/multipart/parser.rb
@@ -2,6 +2,10 @@
 
 require 'strscan'
 
+require_relative '../auth/digest/params'
+require_relative '../utils'
+require_relative '../multipart' unless defined?(Rack::Multipart)
+
 module Rack
   module Multipart
     class MultipartPartLimitError < Errno::EMFILE; end
diff --git a/lib/rack/multipart/uploaded_file.rb b/lib/rack/multipart/uploaded_file.rb
index 9eaf6912..a8db0931 100644
--- a/lib/rack/multipart/uploaded_file.rb
+++ b/lib/rack/multipart/uploaded_file.rb
@@ -1,5 +1,9 @@
 # frozen_string_literal: true
 
+require 'tempfile'
+require 'fileutils'
+require_relative '../multipart'
+
 module Rack
   module Multipart
     class UploadedFile
diff --git a/lib/rack/null_logger.rb b/lib/rack/null_logger.rb
index d4ec3968..46262257 100644
--- a/lib/rack/null_logger.rb
+++ b/lib/rack/null_logger.rb
@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+
 module Rack
   class NullLogger
     def initialize(app)
diff --git a/lib/rack/recursive.rb b/lib/rack/recursive.rb
index 6971cbfd..0945d322 100644
--- a/lib/rack/recursive.rb
+++ b/lib/rack/recursive.rb
@@ -2,6 +2,8 @@
 
 require 'uri'
 
+require_relative 'constants'
+
 module Rack
   # Rack::ForwardRequest gets caught by Rack::Recursive and redirects
   # the current request to the app at +url+.
diff --git a/lib/rack/request.rb b/lib/rack/request.rb
index 1ac50087..9f1c2ce9 100644
--- a/lib/rack/request.rb
+++ b/lib/rack/request.rb
@@ -1,5 +1,9 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+require_relative 'utils'
+require_relative 'media_type'
+
 module Rack
   # Rack::Request provides a convenient interface to a Rack
   # environment.  It is stateless, the environment +env+ passed to the
@@ -660,3 +664,5 @@ module Rack
     include Helpers
   end
 end
+
+require_relative 'multipart' unless defined?(Rack::Multipart)
diff --git a/lib/rack/response.rb b/lib/rack/response.rb
index 593208fe..d6f4c43d 100644
--- a/lib/rack/response.rb
+++ b/lib/rack/response.rb
@@ -2,6 +2,10 @@
 
 require 'time'
 
+require_relative 'constants'
+require_relative 'utils'
+require_relative 'media_type'
+
 module Rack
   # Rack::Response provides a convenient interface to create a Rack
   # response.
diff --git a/lib/rack/runtime.rb b/lib/rack/runtime.rb
index d9b2d8ed..97762b37 100644
--- a/lib/rack/runtime.rb
+++ b/lib/rack/runtime.rb
@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require_relative 'utils'
+
 module Rack
   # Sets an "X-Runtime" response header, indicating the response
   # time of the request, in seconds
diff --git a/lib/rack/sendfile.rb b/lib/rack/sendfile.rb
index 758a48d6..6eccbce2 100644
--- a/lib/rack/sendfile.rb
+++ b/lib/rack/sendfile.rb
@@ -1,5 +1,9 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+require_relative 'utils'
+require_relative 'body_proxy'
+
 module Rack
 
   # = Sendfile
diff --git a/lib/rack/server.rb b/lib/rack/server.rb
index 5a1b45b9..b9034cb5 100644
--- a/lib/rack/server.rb
+++ b/lib/rack/server.rb
@@ -3,6 +3,15 @@
 require 'optparse'
 require 'fileutils'
 
+require_relative 'version'
+require_relative 'handler'
+require_relative 'builder'
+require_relative 'common_logger'
+require_relative 'content_length'
+require_relative 'show_exceptions'
+require_relative 'lint'
+require_relative 'tempfile_reaper'
+
 module Rack
 
   class Server
diff --git a/lib/rack/session/abstract/id.rb b/lib/rack/session/abstract/id.rb
index 80b0f68e..65b93d69 100644
--- a/lib/rack/session/abstract/id.rb
+++ b/lib/rack/session/abstract/id.rb
@@ -3,11 +3,14 @@
 # AUTHOR: blink <blinketje@gmail.com>; blink#ruby-lang@irc.freenode.net
 # bugrep: Andreas Zehnder
 
-require_relative '../../../rack'
 require 'time'
 require 'securerandom'
 require 'digest/sha2'
 
+require_relative '../../constants'
+require_relative '../../request'
+require_relative '../../response'
+
 module Rack
 
   module Session
diff --git a/lib/rack/session/cookie.rb b/lib/rack/session/cookie.rb
index 773d0b8f..653f9539 100644
--- a/lib/rack/session/cookie.rb
+++ b/lib/rack/session/cookie.rb
@@ -2,11 +2,14 @@
 
 require 'openssl'
 require 'zlib'
-require_relative 'abstract/id'
 require 'json'
 require 'base64'
 require 'delegate'
 
+require_relative '../constants'
+require_relative '../utils'
+require_relative 'abstract/id'
+
 module Rack
 
   module Session
diff --git a/lib/rack/session/pool.rb b/lib/rack/session/pool.rb
index 83a359fb..05c567d0 100644
--- a/lib/rack/session/pool.rb
+++ b/lib/rack/session/pool.rb
@@ -6,7 +6,6 @@
 #   sergio, threadiness and bugreps
 
 require_relative 'abstract/id'
-require 'thread'
 
 module Rack
   module Session
diff --git a/lib/rack/show_exceptions.rb b/lib/rack/show_exceptions.rb
index 07e60388..5f2bd7fb 100644
--- a/lib/rack/show_exceptions.rb
+++ b/lib/rack/show_exceptions.rb
@@ -3,6 +3,10 @@
 require 'ostruct'
 require 'erb'
 
+require_relative 'constants'
+require_relative 'utils'
+require_relative 'request'
+
 module Rack
   # Rack::ShowExceptions catches all exceptions raised from the app it
   # wraps.  It shows a useful backtrace with the sourcefile and
diff --git a/lib/rack/show_status.rb b/lib/rack/show_status.rb
index d2593081..6cdff44a 100644
--- a/lib/rack/show_status.rb
+++ b/lib/rack/show_status.rb
@@ -2,6 +2,11 @@
 
 require 'erb'
 
+require_relative 'constants'
+require_relative 'utils'
+require_relative 'request'
+require_relative 'body_proxy'
+
 module Rack
   # Rack::ShowStatus catches all empty responses and replaces them
   # with a site explaining the error.
diff --git a/lib/rack/static.rb b/lib/rack/static.rb
index 88b0a802..e14cd6bb 100644
--- a/lib/rack/static.rb
+++ b/lib/rack/static.rb
@@ -1,5 +1,9 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+require_relative 'files'
+require_relative 'mime'
+
 module Rack
 
   # The Rack::Static middleware intercepts requests for static files
diff --git a/lib/rack/tempfile_reaper.rb b/lib/rack/tempfile_reaper.rb
index 12500f0a..6af0b662 100644
--- a/lib/rack/tempfile_reaper.rb
+++ b/lib/rack/tempfile_reaper.rb
@@ -1,5 +1,8 @@
 # frozen_string_literal: true
 
+require_relative 'constants'
+require_relative 'body_proxy'
+
 module Rack
 
   # Middleware tracks and cleans Tempfiles created throughout a request (i.e. Rack::Multipart)
diff --git a/lib/rack/urlmap.rb b/lib/rack/urlmap.rb
index 31a642c4..c42fedb8 100644
--- a/lib/rack/urlmap.rb
+++ b/lib/rack/urlmap.rb
@@ -2,6 +2,8 @@
 
 require 'set'
 
+require_relative 'constants'
+
 module Rack
   # Rack::URLMap takes a hash mapping urls or paths to apps, and
   # dispatches accordingly.  Support for HTTP/1.1 host names exists if
diff --git a/lib/rack/utils.rb b/lib/rack/utils.rb
index 7d7719c0..20718277 100644
--- a/lib/rack/utils.rb
+++ b/lib/rack/utils.rb
@@ -8,6 +8,7 @@ require 'tempfile'
 require 'time'
 
 require_relative 'query_parser'
+require_relative 'mime'
 
 module Rack
   # Rack::Utils contains a grab-bag of useful methods for writing web
diff --git a/test/helper.rb b/test/helper.rb
index 55799c8c..83f7d0d6 100644
--- a/test/helper.rb
+++ b/test/helper.rb
@@ -16,6 +16,15 @@ if ENV.delete('COVERAGE')
 end
 
 $:.unshift(File.expand_path('../lib', __dir__))
-require_relative '../lib/rack'
+if ENV['SEPARATE']
+  def self.separate_testing
+    yield
+  end
+else
+  require_relative '../lib/rack'
+
+  def self.separate_testing
+  end
+end
 require 'minitest/global_expectations/autorun'
 require 'stringio'
diff --git a/test/psych_fix.rb b/test/psych_fix.rb
new file mode 100644
index 00000000..ef8a5be3
--- /dev/null
+++ b/test/psych_fix.rb
@@ -0,0 +1,8 @@
+# Work correctly with older versions of Psych, having
+# unsafe_load call load (in older versions, load operates
+# as unsafe_load in current version).
+unless YAML.respond_to?(:unsafe_load)
+  def YAML.unsafe_load(body)
+    load(body)
+  end
+end
diff --git a/test/spec_auth_basic.rb b/test/spec_auth_basic.rb
index 7d39b195..5373897c 100644
--- a/test/spec_auth_basic.rb
+++ b/test/spec_auth_basic.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/auth/basic'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/lint'
+end
+
 describe Rack::Auth::Basic do
   def realm
     'WallysWorld'
diff --git a/test/spec_auth_digest.rb b/test/spec_auth_digest.rb
index 6e32152f..6ed1f21e 100644
--- a/test/spec_auth_digest.rb
+++ b/test/spec_auth_digest.rb
@@ -2,6 +2,16 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/auth/digest/md5'
+  require_relative '../lib/rack/auth/digest/nonce'
+  require_relative '../lib/rack/auth/digest/params'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/urlmap'
+  require_relative '../lib/rack/method_override'
+end
+
 describe Rack::Auth::Digest::MD5 do
   def realm
     'WallysWorld'
diff --git a/test/spec_body_proxy.rb b/test/spec_body_proxy.rb
index 1199f2f1..91fcbd74 100644
--- a/test/spec_body_proxy.rb
+++ b/test/spec_body_proxy.rb
@@ -2,6 +2,10 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/body_proxy'
+end
+
 describe Rack::BodyProxy do
   it 'call each on the wrapped body' do
     called = false
diff --git a/test/spec_builder.rb b/test/spec_builder.rb
index eb13a976..078c0f08 100644
--- a/test/spec_builder.rb
+++ b/test/spec_builder.rb
@@ -2,6 +2,15 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/builder'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/content_length'
+  require_relative '../lib/rack/show_exceptions'
+  require_relative '../lib/rack/auth/basic'
+end
+
 class NothingMiddleware
   def initialize(app, **)
     @app = app
diff --git a/test/spec_cascade.rb b/test/spec_cascade.rb
index 8f1fd131..b2529e0e 100644
--- a/test/spec_cascade.rb
+++ b/test/spec_cascade.rb
@@ -2,6 +2,14 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/cascade'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/urlmap'
+  require_relative '../lib/rack/files'
+end
+
 describe Rack::Cascade do
   def cascade(*args)
     Rack::Lint.new Rack::Cascade.new(*args)
diff --git a/test/spec_chunked.rb b/test/spec_chunked.rb
index ceb7bdfb..2c537001 100644
--- a/test/spec_chunked.rb
+++ b/test/spec_chunked.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/chunked'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::Chunked do
   def chunked(app)
     proc do |env|
diff --git a/test/spec_common_logger.rb b/test/spec_common_logger.rb
index dd55c2f8..8a572cbb 100644
--- a/test/spec_common_logger.rb
+++ b/test/spec_common_logger.rb
@@ -3,6 +3,12 @@
 require_relative 'helper'
 require 'logger'
 
+separate_testing do
+  require_relative '../lib/rack/common_logger'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::CommonLogger do
   obj = 'foobar'
   length = obj.size
diff --git a/test/spec_conditional_get.rb b/test/spec_conditional_get.rb
index 5d517be4..6ab69721 100644
--- a/test/spec_conditional_get.rb
+++ b/test/spec_conditional_get.rb
@@ -3,6 +3,12 @@
 require_relative 'helper'
 require 'time'
 
+separate_testing do
+  require_relative '../lib/rack/conditional_get'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::ConditionalGet do
   def conditional_get(app)
     Rack::Lint.new Rack::ConditionalGet.new(app)
diff --git a/test/spec_config.rb b/test/spec_config.rb
index 304ef8bf..531077d1 100644
--- a/test/spec_config.rb
+++ b/test/spec_config.rb
@@ -2,6 +2,13 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/config'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/builder'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::Config do
   it "accept a block that modifies the environment" do
     app = Rack::Builder.new do
diff --git a/test/spec_content_length.rb b/test/spec_content_length.rb
index 4301b89b..a3a5995c 100644
--- a/test/spec_content_length.rb
+++ b/test/spec_content_length.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/content_length'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::ContentLength do
   def content_length(app)
     Rack::Lint.new Rack::ContentLength.new(app)
diff --git a/test/spec_content_type.rb b/test/spec_content_type.rb
index a11d2c9d..93006b06 100644
--- a/test/spec_content_type.rb
+++ b/test/spec_content_type.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/content_type'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::ContentType do
   def content_type(app, *args)
     Rack::Lint.new Rack::ContentType.new(app, *args)
diff --git a/test/spec_deflater.rb b/test/spec_deflater.rb
index ed9cffec..2eb60bd9 100644
--- a/test/spec_deflater.rb
+++ b/test/spec_deflater.rb
@@ -4,6 +4,12 @@ require_relative 'helper'
 require 'time'  # for Time#httpdate
 require 'zlib'
 
+separate_testing do
+  require_relative '../lib/rack/deflater'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::Deflater do
 
   def build_response(status, body, accept_encoding, options = {})
diff --git a/test/spec_directory.rb b/test/spec_directory.rb
index 97cbadbf..9e46e896 100644
--- a/test/spec_directory.rb
+++ b/test/spec_directory.rb
@@ -4,6 +4,14 @@ require_relative 'helper'
 require 'tempfile'
 require 'fileutils'
 
+separate_testing do
+  require_relative '../lib/rack/directory'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/utils'
+  require_relative '../lib/rack/builder'
+end
+
 describe Rack::Directory do
   DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
   FILE_CATCH = proc{|env| [200, { 'Content-Type' => 'text/plain', "Content-Length" => "7" }, ['passed!']] }
diff --git a/test/spec_etag.rb b/test/spec_etag.rb
index 3528b4fa..09c5636c 100644
--- a/test/spec_etag.rb
+++ b/test/spec_etag.rb
@@ -3,6 +3,12 @@
 require_relative 'helper'
 require 'time'
 
+separate_testing do
+  require_relative '../lib/rack/etag'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::ETag do
   def etag(app, *args)
     Rack::Lint.new Rack::ETag.new(app, *args)
diff --git a/test/spec_events.rb b/test/spec_events.rb
index e2077984..3e99e35f 100644
--- a/test/spec_events.rb
+++ b/test/spec_events.rb
@@ -2,6 +2,10 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/events'
+end
+
 module Rack
   class TestEvents < Minitest::Test
     class EventMiddleware
diff --git a/test/spec_files.rb b/test/spec_files.rb
index f8d11b0b..5dfb8c6e 100644
--- a/test/spec_files.rb
+++ b/test/spec_files.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/files'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::Files do
   DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
 
diff --git a/test/spec_handler.rb b/test/spec_handler.rb
index d6d9ccce..f307d158 100644
--- a/test/spec_handler.rb
+++ b/test/spec_handler.rb
@@ -2,6 +2,10 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/handler'
+end
+
 class Rack::Handler::Lobster; end
 class RockLobster; end
 
diff --git a/test/spec_head.rb b/test/spec_head.rb
index d2dedd28..0f0eb0c3 100644
--- a/test/spec_head.rb
+++ b/test/spec_head.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/head'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::Head do
 
   def test_response(headers = {})
diff --git a/test/spec_lint.rb b/test/spec_lint.rb
index d822f985..17c3f150 100755
--- a/test/spec_lint.rb
+++ b/test/spec_lint.rb
@@ -3,6 +3,11 @@
 require_relative 'helper'
 require 'tempfile'
 
+separate_testing do
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::Lint do
   def env(*args)
     Rack::MockRequest.env_for("/", *args)
diff --git a/test/spec_lobster.rb b/test/spec_lobster.rb
index ac3f1193..71584d4b 100644
--- a/test/spec_lobster.rb
+++ b/test/spec_lobster.rb
@@ -1,7 +1,12 @@
 # frozen_string_literal: true
 
 require_relative 'helper'
-require 'rack/lobster'
+
+require_relative '../lib/rack/lobster'
+separate_testing do
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
 
 module LobsterHelpers
   def lobster
diff --git a/test/spec_lock.rb b/test/spec_lock.rb
index c86d5b09..93695dc1 100644
--- a/test/spec_lock.rb
+++ b/test/spec_lock.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/lock'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/lint'
+end
+
 class Lock
   attr_reader :synchronized
 
diff --git a/test/spec_logger.rb b/test/spec_logger.rb
index 8355fc82..6f63f1ae 100644
--- a/test/spec_logger.rb
+++ b/test/spec_logger.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/logger'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::Logger do
   app = lambda { |env|
     log = env['rack.logger']
diff --git a/test/spec_media_type.rb b/test/spec_media_type.rb
index a00a767e..1e701f25 100644
--- a/test/spec_media_type.rb
+++ b/test/spec_media_type.rb
@@ -2,6 +2,10 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/media_type'
+end
+
 describe Rack::MediaType do
   before { @empty_hash = {} }
 
diff --git a/test/spec_method_override.rb b/test/spec_method_override.rb
index 5909907b..199462db 100644
--- a/test/spec_method_override.rb
+++ b/test/spec_method_override.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/method_override'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::MethodOverride do
   def app
     Rack::Lint.new(Rack::MethodOverride.new(lambda {|e|
diff --git a/test/spec_mime.rb b/test/spec_mime.rb
index 65a77f6f..4a8ff7c9 100644
--- a/test/spec_mime.rb
+++ b/test/spec_mime.rb
@@ -2,6 +2,10 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/mime'
+end
+
 describe Rack::Mime do
 
   it "should return the fallback mime-type for files with no extension" do
diff --git a/test/spec_mock.rb b/test/spec_mock.rb
index e81f8d83..072cc352 100644
--- a/test/spec_mock.rb
+++ b/test/spec_mock.rb
@@ -2,14 +2,16 @@
 
 require_relative 'helper'
 require 'yaml'
-
-# Work correctly with older versions of Psych, having
-# unsafe_load call load (in older versions, load operates
-# as unsafe_load in current version).
-unless YAML.respond_to?(:unsafe_load)
-  def YAML.unsafe_load(body)
-    load(body)
-  end
+require_relative 'psych_fix'
+
+separate_testing do
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/request'
+  require_relative '../lib/rack/response'
+  require_relative '../lib/rack/multipart'
+  require_relative '../lib/rack/constants'
+  require_relative '../lib/rack/body_proxy'
 end
 
 app = Rack::Lint.new(lambda { |env|
diff --git a/test/spec_multipart.rb b/test/spec_multipart.rb
index 87902a1f..ad7c1ca5 100644
--- a/test/spec_multipart.rb
+++ b/test/spec_multipart.rb
@@ -3,6 +3,14 @@
 require_relative 'helper'
 require 'timeout'
 
+separate_testing do
+  require_relative '../lib/rack/multipart'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/query_parser'
+  require_relative '../lib/rack/utils'
+end
+
 describe Rack::Multipart do
   def multipart_fixture(name, boundary = "AaB03x")
     file = multipart_file(name)
diff --git a/test/spec_null_logger.rb b/test/spec_null_logger.rb
index 435d051e..8659a8e5 100644
--- a/test/spec_null_logger.rb
+++ b/test/spec_null_logger.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/null_logger'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::NullLogger do
   it "act as a noop logger" do
     app = lambda { |env|
diff --git a/test/spec_recursive.rb b/test/spec_recursive.rb
index 62e3a4f1..1691066e 100644
--- a/test/spec_recursive.rb
+++ b/test/spec_recursive.rb
@@ -2,6 +2,13 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/recursive'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/urlmap'
+end
+
 describe Rack::Recursive do
   before do
   @app1 = lambda { |env|
diff --git a/test/spec_request.rb b/test/spec_request.rb
index d0b0df34..79b612a9 100644
--- a/test/spec_request.rb
+++ b/test/spec_request.rb
@@ -5,6 +5,12 @@ require 'cgi'
 require 'forwardable'
 require 'securerandom'
 
+separate_testing do
+  require_relative '../lib/rack/request'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/lint'
+end
+
 class RackRequestTest < Minitest::Spec
   it "copies the env when duping" do
     req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
diff --git a/test/spec_response.rb b/test/spec_response.rb
index 1dfafcdb..3c25aa0c 100644
--- a/test/spec_response.rb
+++ b/test/spec_response.rb
@@ -2,6 +2,10 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/response'
+end
+
 describe Rack::Response do
   it 'has standard constructor' do
     headers = { "header" => "value" }
diff --git a/test/spec_rewindable_input.rb b/test/spec_rewindable_input.rb
index 1ea84841..5c1bf5c9 100644
--- a/test/spec_rewindable_input.rb
+++ b/test/spec_rewindable_input.rb
@@ -2,6 +2,10 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/rewindable_input'
+end
+
 module RewindableTest
   extend Minitest::Spec::DSL
 
diff --git a/test/spec_runtime.rb b/test/spec_runtime.rb
index e4fc3f95..0b927e9a 100644
--- a/test/spec_runtime.rb
+++ b/test/spec_runtime.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/runtime'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::Runtime do
   def runtime_app(app, *args)
     Rack::Lint.new Rack::Runtime.new(app, *args)
diff --git a/test/spec_sendfile.rb b/test/spec_sendfile.rb
index 09e810e9..f69a3e41 100644
--- a/test/spec_sendfile.rb
+++ b/test/spec_sendfile.rb
@@ -4,6 +4,12 @@ require_relative 'helper'
 require 'fileutils'
 require 'tmpdir'
 
+separate_testing do
+  require_relative '../lib/rack/sendfile'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::Sendfile do
   def sendfile_body(filename = "rack_sendfile")
     FileUtils.touch File.join(Dir.tmpdir,  filename)
diff --git a/test/spec_server.rb b/test/spec_server.rb
index 48b1cabb..1e2d7cfa 100644
--- a/test/spec_server.rb
+++ b/test/spec_server.rb
@@ -8,7 +8,15 @@ require 'open-uri'
 require 'net/http'
 require 'net/https'
 
-require 'rack/handler/cgi'
+separate_testing do
+  require_relative '../lib/rack/server'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/show_exceptions'
+  require_relative '../lib/rack/tempfile_reaper'
+  require_relative '../lib/rack/handler'
+  require_relative '../lib/rack/handler/cgi'
+end
 
 module Minitest::Spec::DSL
   alias :should :it
diff --git a/test/spec_session_abstract_id.rb b/test/spec_session_abstract_id.rb
index 17cdb3e5..9812b530 100644
--- a/test/spec_session_abstract_id.rb
+++ b/test/spec_session_abstract_id.rb
@@ -3,7 +3,10 @@
 require_relative 'helper'
 ### WARNING: there be hax in this file.
 
-require 'rack/session/abstract/id'
+require_relative '../lib/rack/session/abstract/id'
+separate_testing do
+  require_relative '../lib/rack/request'
+end
 
 describe Rack::Session::Abstract::ID do
   attr_reader :id
diff --git a/test/spec_session_abstract_persisted.rb b/test/spec_session_abstract_persisted.rb
index 84ddf072..1b1fce86 100644
--- a/test/spec_session_abstract_persisted.rb
+++ b/test/spec_session_abstract_persisted.rb
@@ -1,7 +1,11 @@
 # frozen_string_literal: true
 
 require_relative 'helper'
-require 'rack/session/abstract/id'
+
+require_relative '../lib/rack/session/abstract/id'
+separate_testing do
+  require_relative '../lib/rack/request'
+end
 
 describe Rack::Session::Abstract::Persisted do
   def setup
diff --git a/test/spec_session_abstract_persisted_secure_secure_session_hash.rb b/test/spec_session_abstract_persisted_secure_secure_session_hash.rb
index bbb8a900..d6d18860 100644
--- a/test/spec_session_abstract_persisted_secure_secure_session_hash.rb
+++ b/test/spec_session_abstract_persisted_secure_secure_session_hash.rb
@@ -1,7 +1,11 @@
 # frozen_string_literal: true
 
 require_relative 'helper'
-require 'rack/session/abstract/id'
+require_relative '../lib/rack/session/abstract/id'
+
+separate_testing do
+  require_relative '../lib/rack/request'
+end
 
 describe Rack::Session::Abstract::PersistedSecure::SecureSessionHash do
   attr_reader :hash
diff --git a/test/spec_session_abstract_session_hash.rb b/test/spec_session_abstract_session_hash.rb
index ac0b7bb3..2a832c1c 100644
--- a/test/spec_session_abstract_session_hash.rb
+++ b/test/spec_session_abstract_session_hash.rb
@@ -1,7 +1,11 @@
 # frozen_string_literal: true
 
 require_relative 'helper'
+
 require 'rack/session/abstract/id'
+separate_testing do
+  require_relative '../lib/rack/request'
+end
 
 describe Rack::Session::Abstract::SessionHash do
   attr_reader :hash
diff --git a/test/spec_session_cookie.rb b/test/spec_session_cookie.rb
index 875c883e..5993dc01 100644
--- a/test/spec_session_cookie.rb
+++ b/test/spec_session_cookie.rb
@@ -2,6 +2,13 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/session/cookie'
+  require_relative '../lib/rack/response'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::Session::Cookie do
   incrementor = lambda do |env|
     env["rack.session"]["counter"] ||= 0
diff --git a/test/spec_session_pool.rb b/test/spec_session_pool.rb
index a8e1f3da..02b196d3 100644
--- a/test/spec_session_pool.rb
+++ b/test/spec_session_pool.rb
@@ -2,6 +2,14 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/session/pool'
+  require_relative '../lib/rack/response'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/utils'
+end
+
 describe Rack::Session::Pool do
   session_key = Rack::Session::Pool::DEFAULT_OPTIONS[:key]
   session_match = /#{session_key}=([0-9a-fA-F]+);/
diff --git a/test/spec_show_exceptions.rb b/test/spec_show_exceptions.rb
index 441599b4..d0fdf0fd 100644
--- a/test/spec_show_exceptions.rb
+++ b/test/spec_show_exceptions.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/show_exceptions'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::ShowExceptions do
   def show_exceptions(app)
     Rack::Lint.new Rack::ShowExceptions.new(app)
diff --git a/test/spec_show_status.rb b/test/spec_show_status.rb
index c5784b16..e8d88b41 100644
--- a/test/spec_show_status.rb
+++ b/test/spec_show_status.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/show_status'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::ShowStatus do
   def show_status(app)
     Rack::Lint.new Rack::ShowStatus.new(app)
diff --git a/test/spec_static.rb b/test/spec_static.rb
index 2a94d68c..b8c02b1f 100644
--- a/test/spec_static.rb
+++ b/test/spec_static.rb
@@ -3,6 +3,12 @@
 require_relative 'helper'
 require 'zlib'
 
+separate_testing do
+  require_relative '../lib/rack/static'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 class DummyApp
   def call(env)
     [200, { "Content-Type" => "text/plain" }, ["Hello World"]]
diff --git a/test/spec_tempfile_reaper.rb b/test/spec_tempfile_reaper.rb
index 4756e53e..ce5d2c76 100644
--- a/test/spec_tempfile_reaper.rb
+++ b/test/spec_tempfile_reaper.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/tempfile_reaper'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::TempfileReaper do
   class MockTempfile
     attr_reader :closed
diff --git a/test/spec_urlmap.rb b/test/spec_urlmap.rb
index 29af5587..db3c676a 100644
--- a/test/spec_urlmap.rb
+++ b/test/spec_urlmap.rb
@@ -2,6 +2,12 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/urlmap'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+end
+
 describe Rack::URLMap do
   it "dispatches paths correctly" do
     app = lambda { |env|
diff --git a/test/spec_utils.rb b/test/spec_utils.rb
index b2d75f27..e588970b 100644
--- a/test/spec_utils.rb
+++ b/test/spec_utils.rb
@@ -3,6 +3,14 @@
 require_relative 'helper'
 require 'timeout'
 
+separate_testing do
+  require_relative '../lib/rack/utils'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/mock'
+  require_relative '../lib/rack/request'
+  require_relative '../lib/rack/content_length'
+end
+
 describe Rack::Utils do
 
   def assert_sets(exp, act)
diff --git a/test/spec_version.rb b/test/spec_version.rb
index 68c4b4c7..d9be54d2 100644
--- a/test/spec_version.rb
+++ b/test/spec_version.rb
@@ -2,6 +2,10 @@
 
 require_relative 'helper'
 
+separate_testing do
+  require_relative '../lib/rack/version'
+end
+
 describe Rack do
   describe 'version' do
     it 'defaults to a hard-coded api version' do
diff --git a/test/spec_webrick.rb b/test/spec_webrick.rb
index ffb03740..96f86c25 100644
--- a/test/spec_webrick.rb
+++ b/test/spec_webrick.rb
@@ -2,8 +2,15 @@
 
 require_relative 'helper'
 require 'thread'
+require 'webrick'
 require_relative 'test_request'
 
+separate_testing do
+  require_relative '../lib/rack/handler'
+  require_relative '../lib/rack/lint'
+  require_relative '../lib/rack/response'
+end
+
 Thread.abort_on_exception = true
 
 describe Rack::Handler::WEBrick do
diff --git a/test/test_request.rb b/test/test_request.rb
index ae995c53..23beecf7 100644
--- a/test/test_request.rb
+++ b/test/test_request.rb
@@ -1,6 +1,7 @@
 # frozen_string_literal: true
 
 require 'yaml'
+require_relative 'psych_fix'
 require 'net/http'
 require 'rack/lint'