1

I'm trying to make make my app buildable via CodeShip.

It builds nicely when using Travis CI (except some integration tests, but this is an another story) and, of course, on my local machine. However, the same code is failed to be tested just in one certain place if CodeShipping. I wouldn't be suprised if the fail was about feature testing, but it fails within a controller spec!

CodeShip error:

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)>'

It's so weird, because there are nearly the same tests below and upper that one. I wouldn't be surprised if the problem was about javascript and features, but it's just a controller test! I'm really frustrated.

CodeShip setup commands:

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 test commands:

export CODECLIMATE_REPO_TOKEN=blahblah
xvfb-run -a bundle exec rspec spec

Action code

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

Test code

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
Vlad Faust
  • 542
  • 6
  • 18

0 Answers0