我正在尝试通过 CodeShip 使我的应用程序可构建。
它在使用 Travis CI 时构建得很好(除了一些集成测试,但这是另一个故事),当然,在我的本地机器上。但是,如果使用 CodeShipping,相同的代码无法仅在某个地方进行测试。如果失败是关于功能测试的,我不会感到惊讶,但它在控制器规范中失败了!
CodeShip 错误:
Failures:
1) ParrotsController GET #index with filters returns by id
Failure/Error: expect(json.count).to eq 1
expected: 1
got: 0
(compared using ==)
# ./spec/controllers/parrots_controller_spec.rb:117:in `block (4 levels) in <top (required)>'
这太奇怪了,因为下面和上面的测试几乎相同。如果问题与 javascript 和功能有关,我不会感到惊讶,但这只是一个控制器测试!我真的很沮丧。
CodeShip 设置命令:
npm install -g bower
bower install
rvm use 2.2.3 --install
bundle install
export RAILS_ENV=test
bundle exec rake db:migrate --trace
bundle exec rake db:test:prepare
bundle exec rake db:schema:load
CodeShip 测试命令:
export CODECLIMATE_REPO_TOKEN=blahblah
xvfb-run -a bundle exec rspec spec
动作代码
def index
# TODO Below code is not ideal, needs optimizing
begin
p = Parrot.all # I could use @parrots everywhere, but 'p' is shorter for bunch of selects
[:ancestors, :descendants, :children, :parents].each do |selector|
(p = p & Parrot.find(params[selector].to_i).try(selector)) if params[selector]
end
# Temporary solution for nil elements within 'p' when wrong 'selector' ids given
p.each { |_p| p.delete _p if _p.nil? } if p
(p = p.select { |_p| _p.age >= params[:age_min].to_i }) if params[:age_min]
(p = p.select { |_p| _p.age <= params[:age_max].to_i }) if params[:age_max]
(p = p.select { |_p| _p.sex == params[:sex] }) if params[:sex]
(p = p.select { |_p| _p.id == params[:id].to_i }) if params[:id]
(p = p.select { |_p| _p.tribal == (params[:tribals] == 'true' || params[:tribal] == true) }) unless params[:tribals].nil?
(p = p.select { |_p| _p.color == Color.find_by_name(params[:color]) }) unless params[:color].blank?
(p = p.select { |_p| _p.name.downcase.include?(params[:name].downcase) }) unless params[:name].blank?
@parrots = p
rescue Exception => e
@error = e
end
respond_to do |format|
format.json do
render layout: false, status: (@error ? :unprocessable_entity : :ok)
end
end
end
index.json.jbuilder
if @error
json.error @error.to_s
else
json.array! @parrots, :id, :name, :age, :color_id, :sex, :tribal, :color_hex
end
测试代码
describe 'GET #index' do
before do
@grandmother = create(:parrot, name: 'FooMother', age: 40, sex: 'female', tribal: true, color_name: 'green')
@grandfather = create(:parrot, name: 'FooFather', age: 50, sex: 'male', tribal: true, color_name: 'green')
@mother = create(:parrot, name: 'Foo', age: 20, sex: 'female', tribal: true, color_name: 'red', father_id: @grandfather.id, mother_id: @grandmother.id)
@father = create(:parrot, name: 'Bar', age: 30, sex: 'male', tribal: true, color_name: 'red')
@son = create(:parrot, name: 'FoobarSon', age: 3, sex: 'male', tribal: true, color_name: 'green', father_id: @father.id, mother_id: @mother.id)
@daughter = create(:parrot, name: 'FoobarDaughter', age: 5, sex: 'female', tribal: false, color_name: 'blue', father_id: @father.id, mother_id: @mother.id)
end
context 'no filters' do
it ' returns all' do
get :index, format: :json
expect(json.count).to eq 6
end
end
context 'with filters' do
it 'returns older than' do
get :index, format: :json, age_min: 20
expect(json.count).to eq 4
expect(json.collect{ |p| p['id'] }).to include @grandmother.id
end
it 'returns younger than' do
get :index, format: :json, age_max: 30
expect(json.count).to eq 4
expect(json.collect{ |p| p['id'] }).to_not include @grandmother.id
end
it 'returns with age in range' do
get :index, format: :json, age_min: 20, age_max: 40
expect(json.count).to eq 3
expect(json.collect{ |p| p['id'] }).to_not include @grandfather.id
expect(json.collect{ |p| p['id'] }).to_not include @son.id
end
it 'returns by id' do # todo doesn't pass in CodeShip only. Why?!
get :index, format: :json, id: 2
expect(json.count).to eq 1
expect(json.collect{ |p| p['name'] }).to include @grandfather.name
end
# Other tests...
end
end