[英]rspec test considerably slower than rails console
I've been spending all day trying to figure out why my rspec-rails test suite takes a really long time to complete (it wasn't always this way) I've used the --profile to determine which tests are taking a long time, and it seems that every test hits the Database takes 30 seconds per query. 我整天都在努力弄清楚为什么我的rspec-rails测试套件需要很长时间才能完成(并非总是这样),我一直使用--profile来确定哪些测试需要很长时间时间,似乎每次测试命中数据库都会使每个查询花费30秒。
Take the following example line: 请看以下示例行:
MyModel.create(args)
If I run this line in the rails console it completes instantaneously, but if I include it in an rspec test, it adds 30 seconds to that test's completion time. 如果我在rails控制台中运行此行,它会立即完成,但是如果我将它包含在rspec测试中,则它将使该测试的完成时间增加30秒。 Also, this line is only an example, if I use Factory girl or create a relation using << the same 30 second tax seems to apply.
另外,如果我使用Factory girl或使用<<创建关系,则此行仅是一个示例,同样适用30秒的税收。
Surely something must be configured wrong. 当然,必须将某些配置错误。
Heres my spec_helper.rb file: 这是我的spec_helper.rb文件:
require 'simplecov'
require 'metric_fu/metrics/rcov/simplecov_formatter'
SimpleCov.formatter = SimpleCov::Formatter::MetricFu
SimpleCov.start 'rails'
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'database_cleaner'
require 'carrierwave'
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
config.mock_with :rspec
config.include JsonSpec::Helpers
config.include FactoryGirl::Syntax::Methods
config.include Devise::TestHelpers, type: :controller
# config.raise_errors_for_deprecations!
config.infer_spec_type_from_file_location!
config.expect_with :rspec do |c|
c.syntax = [:should, :expect]
end
config.before(:suite) do
begin
EphemeralResponse.activate
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
DatabaseCleaner.start
# FactoryGirl.lint
ensure
DatabaseCleaner.clean
end
end
config.before(:each) do
Bullet.start_request if Bullet.enable?
end
config.after(:each) do
if Bullet.enable? #&& Bullet.notification?
# Bullet.perform_out_of_channel_notifications
# Bullet.end_request
end
DatabaseCleaner.clean
end
config.after(:suite) do
EphemeralResponse.deactivate
end
end
I don't really understand a whole lot about rspec, and I didn't write a good portion of this test suite, so maybe this is really obvious to someone, but I've been beating my head against it all day. 我对rspec并不十分了解,我也没有编写此测试套件的大部分内容,因此对于某些人来说这也许确实很明显,但是我整天都在反对。
Edit: I'm going to add one of my model tests: This one takes over 5 minutes to run... 编辑:我要添加我的模型测试之一:这需要5分钟以上才能运行...
require 'spec_helper'
describe CourseAssignment do
let(:instructor) { create(:instructor) }
let(:student) { create(:student, id: 2) }
let(:bundle) { create(:bundle) }
let(:course) { create(:course) }
let(:assignment) { create(:course_assignment, course: course) }
it { should belong_to(:course) }
it { should belong_to(:user) }
describe 'CourseAssignment deletion' do
it 'should not delete the Course or the Student' do
instructor.courses << course # 30 seconds
instructor.courses.last.students << student # 30 seconds
CourseAssignment.create(course_id: course.id, user_id: student.id) # 30 seconds
expect{CourseAssignment.last.destroy}.to change(CourseAssignment, :count).by(-1)
expect(Student.count).to eq(1)
expect(Course.count).to eq(1)
expect(instructor.courses).to include(course)
end
end
describe 'Student deletion' do
it 'should delete the CourseAssignment & Student, but not the Course' do
instructor.courses << course # 30 seconds
instructor.courses.last.students << student # 30 seconds
CourseAssignment.create(course_id: course.id, user_id: student.id) # 30 seconds
expect(student.course_assignments.count).to eq(2)
expect{student.destroy}.to change(CourseAssignment, :count).by(-2)
expect(Course.last.students).to be_empty
expect(Course.count).to eq(1)
expect(instructor.courses).to include(course)
end
end
describe 'Course deletion' do
it 'should delete the CourseAssignment' do
instructor.courses << course # 30 seconds
instructor.courses.last.students << student # 30 seconds
CourseAssignment.create(course_id: course.id, user_id: student.id)
expect{course.destroy}.to change(Course, :count).by(-1)
expect(CourseAssignment.count).to be(0)
instructor.reload
expect(instructor.courses).to be_empty
end
end
it 'should require a course_id' do
no_course_id_assignment = CourseAssignment.create(course_id: '', user_id: 2) # 30 seconds
no_course_id_assignment.should_not be_valid
end
it 'should require a user_id' do
no_student_id_assignment = CourseAssignment.create(course_id: 2, user_id: '') # 30 seconds
no_student_id_assignment.should_not be_valid
end
end
EDIT 2: I figured out that this has something to do with my computer (Mac os x 10.10.5). 编辑2:我发现这与我的计算机(Mac os x 10.10.5)有关。 When I run our test suite on circle ci it the whole suite runs in less than 5 minutes.
当我在ci圈子上运行测试套件时,整个套件在不到5分钟的时间内运行。
Edit 3: Heres my database.yml 编辑3:这是我的database.yml
# MySQL. Versions 4.1 and 5.0 are recommended.
#
# Install the MySQL driver:
# gem install mysql2
#
# And be sure to use new-style password hashing:
# http://dev.mysql.com/doc/refman/5.0/en/old-client.html
development:
adapter: mysql2
encoding: utf8
database: xxxx
username: xxxx
password: xxxx
host: localhost
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
adapter: mysql2
encoding: utf8
database: xxxx_test
username: xxxx
password: xxxx
host: localhost
production:
adapter: mysql2
encoding: utf8
host: localhost
database: xxxx
username: xxxx
password: xxxx
port: 3306
Edit 4: Just figured out that changing my wifi network fixes the issue. 编辑4:刚发现更改我的wifi网络可以解决此问题。 The problem seems to be related to an outage associated with the first network where mixpanel.com is unreachable.
该问题似乎与与无法访问mixpanel.com的第一个网络相关的中断有关。
When you execute rails c
, note that it takes some time to load since it is starting up the DB and loading Rails classes which will be available "instantly". 执行
rails c
,请注意,由于它正在启动数据库并加载“立即”可用的Rails类,因此加载会花费一些时间。
Each test spec recreates a clean DB slate each time, so it should take more time than running the same command in the console (because the DB is already set up). 每个测试规范每次都会重新创建一个干净的数据库,因此比在控制台中运行同一命令要花费更多的时间(因为该数据库已经设置)。 You can mitigate this by correctly using
before(:all)
and setting up tests in such a way that the the same instance is used as much as possible without needing a clean slate. 您可以通过正确地使用
before(:all)
并设置测试来减轻这种情况,从而尽可能多地使用同一实例而无需清理表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.