Как устранить нестабильные характеристики?

У меня на моем CICD случайно происходит сбой Ruby Rspec (локально не происходит сбой).

Это уменьшенная часть моего RSpec:

require "rails_helper"

RSpec.describe "Admin::Vendors", type: :request do
  let!(:vendors) {
    create_list(:vendor, 5, type: 1) do |vendor|
      create(:vendor_user, vendor_id: vendor.id, role: "vendor")
    end

    create_list(:vendor, 5, type: 2) do |vendor|
      create(:vendor_user, vendor_id: vendor.id, role: "vendor")
    end

    create_list(:vendor, 5, status: "waiting_for_approval") do |vendor|
      create(:vendor_user, vendor_id: vendor.id, role: "vendor")
    end

    create_list(:vendor, 5, status: "inactive") do |vendor|
      create(:vendor_user, vendor_id: vendor.id, role: "vendor")
    end
  }
  
  describe "index" do
    context "(success - display the list of vendors by vendor name asc)" do
      before { get "/api/v1/vendor_management/admin/vendors?sort_column=vendor_name&sort_by=asc", headers: headers[:auth] }

      it "returns list of vendors in asc order" do
        asc_vendor_names = json["vendors"].pluck("name")
        expect(json).not_to be_empty
        expect(json["vendors"]).not_to be_empty
        expect(response).to have_http_status(200)
        expect(asc_vendor_names).to eq(asc_vendor_names.sort)
      end
    end

    context "(success - display the list of vendors by vendor name desc)" do
      before { get "/api/v1/vendor_management/admin/vendors?sort_column=vendor_name&sort_by=desc", headers: headers[:auth] }

      it "returns list of vendors in desc order" do
        desc_vendor_names = json["vendors"].pluck("name")
        expect(json).not_to be_empty
        expect(json["vendors"]).not_to be_empty
        expect(response).to have_http_status(200)
        expect(desc_vendor_names).to eq(desc_vendor_names.sort.reverse)
      end
    end
  end

end

и по какой-то причине в 70% случаев в моем конвейере возникает этот сбой:

Failures:

  1) Admin::VendorManagement::VendorController index (success - display the list of vendors by vendor name desc) returns list of vendors in desc order
     Failure/Error: expect(desc_vendor_names).to eq(desc_vendor_names.sort.reverse)
     
       expected: ["Wyatt Conn", "Vikki Rowe VM", "Rocco Bauch", "Randal Muller", "Noe Koch", "Natashia Stark", "Miss L...oe Walter", "Dwain Stoltenberg", "Chara Orn", "Benito Hegmann", "Armida Kuphal", "Agustin Mosciski"]
            got: ["Wyatt Conn", "Vikki Rowe VM", "Rocco Bauch", "Randal Muller", "Noe Koch", "Natashia Stark", "Miss L...h Murazik", "Dwain Stoltenberg", "Chara Orn", "Benito Hegmann", "Armida Kuphal", "Agustin Mosciski"]
     
       (compared using ==)

Я не могу понять, что может быть причиной повреждения данных? как это решить? Спасибо!

🤔 А знаете ли вы, что...
Ruby on Rails активно соблюдает принцип REST (Representational State Transfer) для построения веб-сервисов.


1
60
1

Ответ:

Решено

На этот вопрос сложно дать конкретный ответ, поскольку в вашем вопросе отсутствует ключевая информация. В частности, в сообщении об ошибке говорится:

..., "Natashia Stark", "Miss L...oe Walter", "Dwain Stoltenberg", ...
..., "Natashia Stark", "Miss L...h Murazik", "Dwain Stoltenberg", ...

Но в чем же эта критическая разница между ...oe Walter и ...h Murazik? Какие значения на самом деле находятся в другом порядке и, следовательно, вызывают сбой?

Вы можете записать полные строки, чтобы точно увидеть, что изменилось. Я предполагаю, что это будет что-то вроде mr Tom... и Mr Bob..., где первая буква будет строчной.


В любом случае, неудачная строка в тесте:

expect(desc_vendor_names).to eq(desc_vendor_names.sort.reverse)

Я думаю, что единственный способ, которым это может потерпеть неудачу (если только не произойдет что-то действительно странное), заключается в том, что левая часть сортирует по алфавиту в SQL, а правая сторона сортирует по алфавиту в Ruby.

Почему это имеет значение? Потому что .sort Ruby основан на кодах UTF8, тогда как ваша база данных, вероятно, использует какие-то другие параметры сортировки. Это может привести к различным тонким различиям в порядке сортировки, если строки содержат символы с диакритическими знаками (é, ø, į, ...) или символы верхнего и нижнего регистра.

Например, учитывая строки: ['test 1', 'Test 2'], они (вероятно) будут отсортированы в другом порядке в Ruby и в базе данных.


Так как же можно исправить тест?

Я бы рекомендовал просто убедиться, что ваши фабрики/фикстуры/инициализатор используют имена, которые не вызовут проблем, т. е. ничего, что начинается со строчной буквы или «необычного» акцентированного символа, чтобы ваши порядки сортировки Ruby и SQL были такой же.

В качестве альтернативы вы можете использовать что-то более надежное, чтобы Ruby .sort вел себя так же, как SQL, например:

# probably good enough!
.sort_by(&:downcase)

# Also accounts for most accented character issues:
.sort do |a, b|
  I18n.transliterate(a.downcase) <=> I18n.transliterate(b.downcase)
end

# Hardcore solution:
https://github.com/ninjudd/icunicode