1

我正在尝试通过 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
4

0 回答 0