CodeShip でアプリをビルドできるようにしようとしています。
Travis CI を使用すると (いくつかの統合テストを除きますが、これは別の話です)、もちろん私のローカル マシンでうまくビルドされます。ただし、CodeShipping の場合、同じコードを特定の 1 か所だけでテストするのに失敗します。失敗が機能テストに関するものであったとしても驚かないでしょうが、コントローラーの仕様内で失敗します!
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