У меня на моем 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 ==)
Я не могу понять, что может быть причиной повреждения данных? как это решить? Спасибо!
Ваша нынешняя неудача - между "Старком" и "Столтенбергом". В настоящее время они имеют разные имена, что, исходя из кода, совершенно невозможно, поскольку вы сравниваете один и тот же список. Можете ли вы объяснить, как это происходит?
@engineersmnky именно мое замешательство! Я сортирую список ответов локально и сравниваю сам с собой! понятия не имею, как это происходит, более того - это происходит не локально, а только в моем кругообороте
@AntonBogdanov Я не думаю, что это проблема с сортировкой, в основном потому, что это происходит только случайным образом и в моем конвейере cicd (никогда локально), в любом случае рекомендуется попробовать вставить значения вручную, я попробую, спасибо
На этот вопрос сложно дать конкретный ответ, поскольку в вашем вопросе отсутствует ключевая информация. В частности, в сообщении об ошибке говорится:
..., "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
Спасибо @Tom Lord, я добавил журналирование в тесты и обнаружил проблему - каждый раз, когда Faker создавал имена с помощью "." (точки) сортировка пошла не так, как было предложено - сортировка SQL и сортировка Ruby отдали приоритет "." разные (один больше алфавита, другой меньше). На самом деле я решил эту проблему, обновив инструкцию Faker следующим образом: name { Faker::Name.name.gsub(/\W/, '').gsub("\u0000", '') }
вероятно, существует другая сортировка - в контроллере есть
order(name: :asc)
и сортировка, выполняемая sql, в тесте есть.sort
и сортировка, выполняемая Ruby, поэтому, вероятно, сортировки различаются, в качестве решения вы можете создатьvendor_users с конкретными именами (не от фейкера), чтобы быть уверенным в порядке сортировки и, возможно, просто проверьте первый элемент (не весь список)