Skip to content
Snippets Groups Projects
Commit cfff4ab8 authored by Bob Van Landuyt :neckbeard:'s avatar Bob Van Landuyt :neckbeard: :sunglasses:
Browse files

Merge branch 'eb-rename-ci-test-tables' into 'master'

Create new unit test tables

See merge request gitlab-org/gitlab!56137
parents fc6442e2 8a21dab1
No related branches found
No related tags found
No related merge requests found
Showing
with 448 additions and 61 deletions
# frozen_string_literal: true
 
module Ci
class TestCase < ApplicationRecord
class UnitTest < ApplicationRecord
extend Gitlab::Ci::Model
 
validates :project, :key_hash, presence: true
MAX_NAME_SIZE = 255
MAX_SUITE_NAME_SIZE = 255
 
has_many :test_case_failures, class_name: 'Ci::TestCaseFailure'
validates :project, :key_hash, :name, :suite_name, presence: true
has_many :unit_test_failures, class_name: 'Ci::UnitTestFailure'
 
belongs_to :project
 
scope :by_project_and_keys, -> (project, keys) { where(project_id: project.id, key_hash: keys) }
 
class << self
def find_or_create_by_batch(project, test_case_keys)
def find_or_create_by_batch(project, unit_test_attrs)
# Insert records first. Existing ones will be skipped.
insert_all(test_case_attrs(project, test_case_keys))
insert_all(build_insert_attrs(project, unit_test_attrs))
 
# Find all matching records now that we are sure they all are persisted.
by_project_and_keys(project, test_case_keys)
by_project_and_keys(project, gather_keys(unit_test_attrs))
end
 
private
 
def test_case_attrs(project, test_case_keys)
def build_insert_attrs(project, unit_test_attrs)
# NOTE: Rails 6.1 will add support for insert_all on relation so that
# we will be able to do project.test_cases.insert_all.
test_case_keys.map do |hashed_key|
{ project_id: project.id, key_hash: hashed_key }
unit_test_attrs.map do |attrs|
attrs.merge(
project_id: project.id,
name: attrs[:name].truncate(MAX_NAME_SIZE),
suite_name: attrs[:suite_name].truncate(MAX_SUITE_NAME_SIZE)
)
end
end
def gather_keys(unit_test_attrs)
unit_test_attrs.map { |attrs| attrs[:key_hash] }
end
end
end
end
# frozen_string_literal: true
 
module Ci
class TestCaseFailure < ApplicationRecord
class UnitTestFailure < ApplicationRecord
extend Gitlab::Ci::Model
 
REPORT_WINDOW = 14.days
 
validates :test_case, :build, :failed_at, presence: true
validates :unit_test, :build, :failed_at, presence: true
 
belongs_to :test_case, class_name: "Ci::TestCase", foreign_key: :test_case_id
belongs_to :unit_test, class_name: "Ci::UnitTest", foreign_key: :unit_test_id
belongs_to :build, class_name: "Ci::Build", foreign_key: :build_id
 
def self.recent_failures_count(project:, test_case_keys:, date_range: REPORT_WINDOW.ago..Time.current)
joins(:test_case)
def self.recent_failures_count(project:, unit_test_keys:, date_range: REPORT_WINDOW.ago..Time.current)
joins(:unit_test)
.where(
ci_test_cases: {
ci_unit_tests: {
project_id: project.id,
key_hash: test_case_keys
key_hash: unit_test_keys
},
ci_test_case_failures: {
ci_unit_test_failures: {
failed_at: date_range
}
)
.group(:key_hash)
.count('ci_test_case_failures.id')
.count('ci_unit_test_failures.id')
end
end
end
Loading
Loading
@@ -34,7 +34,7 @@ def should_track_failures?
 
# We fetch for up to MAX_TRACKABLE_FAILURES + 1 builds. So if ever we get
# 201 total number of builds with the assumption that each job has at least
# 1 failed test case, then we have at least 201 failed test cases which exceeds
# 1 failed unit test, then we have at least 201 failed unit tests which exceeds
# the MAX_TRACKABLE_FAILURES of 200. If this is the case, let's early exit so we
# don't have to parse each JUnit report of each of the 201 builds.
failed_builds.length <= MAX_TRACKABLE_FAILURES
Loading
Loading
@@ -51,25 +51,29 @@ def failed_builds
end
 
def track_failures
failed_test_cases = gather_failed_test_cases(failed_builds)
failed_unit_tests = gather_failed_unit_tests_from_reports(failed_builds)
 
return if failed_test_cases.size > MAX_TRACKABLE_FAILURES
return if failed_unit_tests.size > MAX_TRACKABLE_FAILURES
 
failed_test_cases.keys.each_slice(100) do |key_hashes|
Ci::TestCase.transaction do
ci_test_cases = Ci::TestCase.find_or_create_by_batch(project, key_hashes)
failures = test_case_failures(ci_test_cases, failed_test_cases)
failed_unit_tests.each_slice(100) do |batch|
Ci::UnitTest.transaction do
unit_test_attrs = ci_unit_test_attrs(batch)
ci_unit_tests = Ci::UnitTest.find_or_create_by_batch(project, unit_test_attrs)
 
Ci::TestCaseFailure.insert_all(failures)
failures = ci_unit_test_failure_attrs(ci_unit_tests, failed_unit_tests)
Ci::UnitTestFailure.insert_all(failures)
end
end
end
 
def gather_failed_test_cases(failed_builds)
failed_builds.each_with_object({}) do |build, failed_test_cases|
def gather_failed_unit_tests_from_reports(failed_builds)
failed_builds.each_with_object({}) do |build, failed_unit_tests|
test_suite = generate_test_suite!(build)
test_suite.failed.keys.each do |key|
failed_test_cases[key] = build
test_suite.failed.each do |key, unit_test|
failed_unit_tests[key] = {
build: build, # This will be used in ci_unit_test_failure_attrs
unit_test: unit_test # This will be used in ci_unit_test_attrs
}
end
end
end
Loading
Loading
@@ -79,12 +83,24 @@ def generate_test_suite!(build)
build.collect_test_reports!(Gitlab::Ci::Reports::TestReports.new)
end
 
def test_case_failures(ci_test_cases, failed_test_cases)
ci_test_cases.map do |test_case|
build = failed_test_cases[test_case.key_hash]
def ci_unit_test_attrs(batch)
batch.map do |item|
unit_test = item.last[:unit_test]
 
{
test_case_id: test_case.id,
key_hash: unit_test.key,
name: unit_test.name,
suite_name: unit_test.suite_name
}
end
end
def ci_unit_test_failure_attrs(ci_unit_tests, failed_unit_tests)
ci_unit_tests.map do |ci_unit_test|
build = failed_unit_tests[ci_unit_test.key_hash][:build]
{
unit_test_id: ci_unit_test.id,
build_id: build.id,
failed_at: build.finished_at
}
Loading
Loading
---
title: Create new unit test tables
merge_request: 56137
author:
type: other
# frozen_string_literal: true
class CreateCiUnitTests < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
unless table_exists?(:ci_unit_tests)
create_table :ci_unit_tests do |t|
t.bigint :project_id, null: false
t.text :key_hash, null: false
t.text :name, null: false
t.text :suite_name, null: false
t.index [:project_id, :key_hash], unique: true
# NOTE: FK for projects will be added on a separate migration as per guidelines
end
end
add_text_limit :ci_unit_tests, :key_hash, 64
add_text_limit :ci_unit_tests, :name, 255
add_text_limit :ci_unit_tests, :suite_name, 255
end
def down
drop_table :ci_unit_tests
end
end
# frozen_string_literal: true
class AddProjectsFkToCiUnitTests < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_foreign_key :ci_unit_tests, :projects, column: :project_id, on_delete: :cascade
end
def down
with_lock_retries do
remove_foreign_key :ci_unit_tests, column: :project_id
end
end
end
# frozen_string_literal: true
class CreateCiUnitTestFailures < ActiveRecord::Migration[6.0]
DOWNTIME = false
def up
create_table :ci_unit_test_failures do |t|
t.datetime_with_timezone :failed_at, null: false
t.bigint :unit_test_id, null: false
t.bigint :build_id, null: false
t.index [:unit_test_id, :failed_at, :build_id], name: 'index_unit_test_failures_unique_columns', unique: true, order: { failed_at: :desc }
t.index :build_id
# NOTE: Adding the index for failed_at now for later use when we do scheduled clean up
t.index :failed_at, order: { failed_at: :desc }, name: 'index_unit_test_failures_failed_at'
t.foreign_key :ci_unit_tests, column: :unit_test_id, on_delete: :cascade
# NOTE: FK for ci_builds will be added on a separate migration as per guidelines
end
end
def down
drop_table :ci_unit_test_failures
end
end
# frozen_string_literal: true
class AddCiBuildsFkToCiUnitTestFailures < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_foreign_key :ci_unit_test_failures, :ci_builds, column: :build_id, on_delete: :cascade
end
def down
with_lock_retries do
remove_foreign_key :ci_unit_test_failures, column: :build_id
end
end
end
cf63d7ffd6bfb93c25c894b26424e9890b43652b4f0bfc259917a4857ff414e2
\ No newline at end of file
4c1ae24594ccb85706a4c9836ed1fc8ce47d68863262e90b9109ddc1d83d121b
\ No newline at end of file
8f9957b7f7744e3d72bba1b2bf9bd2c9a06203091bf8f9dcafc69755db25fef0
\ No newline at end of file
43af4a4200ba87ebb50627d341bb324896cbe0c36896d50dd81a8a9cfb2eb426
\ No newline at end of file
Loading
Loading
@@ -11130,6 +11130,42 @@ CREATE SEQUENCE ci_triggers_id_seq
 
ALTER SEQUENCE ci_triggers_id_seq OWNED BY ci_triggers.id;
 
CREATE TABLE ci_unit_test_failures (
id bigint NOT NULL,
failed_at timestamp with time zone NOT NULL,
unit_test_id bigint NOT NULL,
build_id bigint NOT NULL
);
CREATE SEQUENCE ci_unit_test_failures_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE ci_unit_test_failures_id_seq OWNED BY ci_unit_test_failures.id;
CREATE TABLE ci_unit_tests (
id bigint NOT NULL,
project_id bigint NOT NULL,
key_hash text NOT NULL,
name text NOT NULL,
suite_name text NOT NULL,
CONSTRAINT check_248fae1a3b CHECK ((char_length(name) <= 255)),
CONSTRAINT check_b288215ffe CHECK ((char_length(key_hash) <= 64)),
CONSTRAINT check_c2d57b3c49 CHECK ((char_length(suite_name) <= 255))
);
CREATE SEQUENCE ci_unit_tests_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE ci_unit_tests_id_seq OWNED BY ci_unit_tests.id;
CREATE TABLE ci_variables (
id integer NOT NULL,
key character varying NOT NULL,
Loading
Loading
@@ -19121,6 +19157,10 @@ ALTER TABLE ONLY ci_trigger_requests ALTER COLUMN id SET DEFAULT nextval('ci_tri
 
ALTER TABLE ONLY ci_triggers ALTER COLUMN id SET DEFAULT nextval('ci_triggers_id_seq'::regclass);
 
ALTER TABLE ONLY ci_unit_test_failures ALTER COLUMN id SET DEFAULT nextval('ci_unit_test_failures_id_seq'::regclass);
ALTER TABLE ONLY ci_unit_tests ALTER COLUMN id SET DEFAULT nextval('ci_unit_tests_id_seq'::regclass);
ALTER TABLE ONLY ci_variables ALTER COLUMN id SET DEFAULT nextval('ci_variables_id_seq'::regclass);
 
ALTER TABLE ONLY cluster_agent_tokens ALTER COLUMN id SET DEFAULT nextval('cluster_agent_tokens_id_seq'::regclass);
Loading
Loading
@@ -20291,6 +20331,12 @@ ALTER TABLE ONLY ci_trigger_requests
ALTER TABLE ONLY ci_triggers
ADD CONSTRAINT ci_triggers_pkey PRIMARY KEY (id);
 
ALTER TABLE ONLY ci_unit_test_failures
ADD CONSTRAINT ci_unit_test_failures_pkey PRIMARY KEY (id);
ALTER TABLE ONLY ci_unit_tests
ADD CONSTRAINT ci_unit_tests_pkey PRIMARY KEY (id);
ALTER TABLE ONLY ci_variables
ADD CONSTRAINT ci_variables_pkey PRIMARY KEY (id);
 
Loading
Loading
@@ -22172,6 +22218,10 @@ CREATE INDEX index_ci_triggers_on_owner_id ON ci_triggers USING btree (owner_id)
 
CREATE INDEX index_ci_triggers_on_project_id ON ci_triggers USING btree (project_id);
 
CREATE INDEX index_ci_unit_test_failures_on_build_id ON ci_unit_test_failures USING btree (build_id);
CREATE UNIQUE INDEX index_ci_unit_tests_on_project_id_and_key_hash ON ci_unit_tests USING btree (project_id, key_hash);
CREATE INDEX index_ci_variables_on_key ON ci_variables USING btree (key);
 
CREATE UNIQUE INDEX index_ci_variables_on_project_id_and_key_and_environment_scope ON ci_variables USING btree (project_id, key, environment_scope);
Loading
Loading
@@ -23884,6 +23934,10 @@ CREATE INDEX index_u2f_registrations_on_key_handle ON u2f_registrations USING bt
 
CREATE INDEX index_u2f_registrations_on_user_id ON u2f_registrations USING btree (user_id);
 
CREATE INDEX index_unit_test_failures_failed_at ON ci_unit_test_failures USING btree (failed_at DESC);
CREATE UNIQUE INDEX index_unit_test_failures_unique_columns ON ci_unit_test_failures USING btree (unit_test_id, failed_at DESC, build_id);
CREATE INDEX index_uploads_on_checksum ON uploads USING btree (checksum);
 
CREATE INDEX index_uploads_on_model_id_and_model_type ON uploads USING btree (model_id, model_type);
Loading
Loading
@@ -24517,6 +24571,9 @@ ALTER TABLE ONLY notification_settings
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_0d3f677137 FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
 
ALTER TABLE ONLY ci_unit_test_failures
ADD CONSTRAINT fk_0f09856e1f FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
ALTER TABLE ONLY project_pages_metadata
ADD CONSTRAINT fk_0fd5b22688 FOREIGN KEY (pages_deployment_id) REFERENCES pages_deployments(id) ON DELETE SET NULL;
 
Loading
Loading
@@ -24763,6 +24820,9 @@ ALTER TABLE ONLY geo_event_log
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_7a5553d60f FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
 
ALTER TABLE ONLY ci_unit_tests
ADD CONSTRAINT fk_7a8fabf0a8 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY protected_branches
ADD CONSTRAINT fk_7a9c6d93e7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
 
Loading
Loading
@@ -25423,6 +25483,9 @@ ALTER TABLE ONLY group_custom_attributes
ALTER TABLE ONLY incident_management_oncall_rotations
ADD CONSTRAINT fk_rails_256e0bc604 FOREIGN KEY (oncall_schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE;
 
ALTER TABLE ONLY ci_unit_test_failures
ADD CONSTRAINT fk_rails_259da3e79c FOREIGN KEY (unit_test_id) REFERENCES ci_unit_tests(id) ON DELETE CASCADE;
ALTER TABLE ONLY analytics_devops_adoption_snapshots
ADD CONSTRAINT fk_rails_25da9a92c0 FOREIGN KEY (segment_id) REFERENCES analytics_devops_adoption_segments(id) ON DELETE CASCADE;
 
Loading
Loading
@@ -6,32 +6,32 @@ module Reports
class TestFailureHistory
include Gitlab::Utils::StrongMemoize
 
def initialize(failed_test_cases, project)
@failed_test_cases = build_map(failed_test_cases)
def initialize(failed_junit_tests, project)
@failed_junit_tests = build_map(failed_junit_tests)
@project = project
end
 
def load!
recent_failures_count.each do |key_hash, count|
failed_test_cases[key_hash].set_recent_failures(count, project.default_branch_or_master)
failed_junit_tests[key_hash].set_recent_failures(count, project.default_branch_or_master)
end
end
 
private
 
attr_reader :report, :project, :failed_test_cases
attr_reader :report, :project, :failed_junit_tests
 
def recent_failures_count
::Ci::TestCaseFailure.recent_failures_count(
::Ci::UnitTestFailure.recent_failures_count(
project: project,
test_case_keys: failed_test_cases.keys
unit_test_keys: failed_junit_tests.keys
)
end
 
def build_map(test_cases)
def build_map(junit_tests)
{}.tap do |hash|
test_cases.each do |test_case|
hash[test_case.key] = test_case
junit_tests.each do |test|
hash[test.key] = test
end
end
end
Loading
Loading
# frozen_string_literal: true
 
FactoryBot.define do
factory :ci_test_case, class: 'Ci::TestCase' do
factory :ci_unit_test, class: 'Ci::UnitTest' do
project
suite_name { 'rspec' }
name { 'Math#add returns sum' }
key_hash { Digest::SHA256.hexdigest(SecureRandom.hex) }
end
end
# frozen_string_literal: true
 
FactoryBot.define do
factory :ci_test_case_failure, class: 'Ci::TestCaseFailure' do
factory :ci_unit_test_failure, class: 'Ci::UnitTestFailure' do
build factory: :ci_build
test_case factory: :ci_test_case
unit_test factory: :ci_unit_test
failed_at { Time.current }
end
end
Loading
Loading
@@ -13,9 +13,9 @@
subject(:load_history) { described_class.new([failed_rspec, failed_java], project).load! }
 
before do
allow(Ci::TestCaseFailure)
allow(Ci::UnitTestFailure)
.to receive(:recent_failures_count)
.with(project: project, test_case_keys: [failed_rspec.key, failed_java.key])
.with(project: project, unit_test_keys: [failed_rspec.key, failed_java.key])
.and_return(
failed_rspec.key => 2,
failed_java.key => 1
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::TestCase do
describe 'relationships' do
it { is_expected.to belong_to(:project) }
it { is_expected.to have_many(:test_case_failures) }
end
describe 'validations' do
subject { build(:ci_test_case) }
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_presence_of(:key_hash) }
end
describe '.find_or_create_by_batch' do
it 'finds or creates records for the given test case keys', :aggregate_failures do
project = create(:project)
existing_tc = create(:ci_test_case, project: project)
new_key = Digest::SHA256.hexdigest(SecureRandom.hex)
keys = [existing_tc.key_hash, new_key]
result = described_class.find_or_create_by_batch(project, keys)
expect(result.map(&:key_hash)).to match_array([existing_tc.key_hash, new_key])
expect(result).to all(be_persisted)
end
end
end
Loading
Loading
@@ -2,16 +2,16 @@
 
require 'spec_helper'
 
RSpec.describe Ci::TestCaseFailure do
RSpec.describe Ci::UnitTestFailure do
describe 'relationships' do
it { is_expected.to belong_to(:build) }
it { is_expected.to belong_to(:test_case) }
it { is_expected.to belong_to(:unit_test) }
end
 
describe 'validations' do
subject { build(:ci_test_case_failure) }
subject { build(:ci_unit_test_failure) }
 
it { is_expected.to validate_presence_of(:test_case) }
it { is_expected.to validate_presence_of(:unit_test) }
it { is_expected.to validate_presence_of(:build) }
it { is_expected.to validate_presence_of(:failed_at) }
end
Loading
Loading
@@ -22,51 +22,51 @@
subject(:recent_failures) do
described_class.recent_failures_count(
project: project,
test_case_keys: test_case_keys
unit_test_keys: unit_test_keys
)
end
 
context 'when test case failures are within the date range and are for the test case keys' do
let(:tc_1) { create(:ci_test_case, project: project) }
let(:tc_2) { create(:ci_test_case, project: project) }
let(:test_case_keys) { [tc_1.key_hash, tc_2.key_hash] }
context 'when unit test failures are within the date range and are for the unit test keys' do
let(:test_1) { create(:ci_unit_test, project: project) }
let(:test_2) { create(:ci_unit_test, project: project) }
let(:unit_test_keys) { [test_1.key_hash, test_2.key_hash] }
 
before do
create_list(:ci_test_case_failure, 3, test_case: tc_1, failed_at: 1.day.ago)
create_list(:ci_test_case_failure, 2, test_case: tc_2, failed_at: 3.days.ago)
create_list(:ci_unit_test_failure, 3, unit_test: test_1, failed_at: 1.day.ago)
create_list(:ci_unit_test_failure, 2, unit_test: test_2, failed_at: 3.days.ago)
end
 
it 'returns the number of failures for each test case key hash for the past 14 days by default' do
it 'returns the number of failures for each unit test key hash for the past 14 days by default' do
expect(recent_failures).to eq(
tc_1.key_hash => 3,
tc_2.key_hash => 2
test_1.key_hash => 3,
test_2.key_hash => 2
)
end
end
 
context 'when test case failures are within the date range but are not for the test case keys' do
let(:tc) { create(:ci_test_case, project: project) }
let(:test_case_keys) { ['some-other-key-hash'] }
context 'when unit test failures are within the date range but are not for the unit test keys' do
let(:test) { create(:ci_unit_test, project: project) }
let(:unit_test_keys) { ['some-other-key-hash'] }
 
before do
create(:ci_test_case_failure, test_case: tc, failed_at: 1.day.ago)
create(:ci_unit_test_failure, unit_test: test, failed_at: 1.day.ago)
end
 
it 'excludes them from the count' do
expect(recent_failures[tc.key_hash]).to be_nil
expect(recent_failures[test.key_hash]).to be_nil
end
end
 
context 'when test case failures are not within the date range but are for the test case keys' do
let(:tc) { create(:ci_test_case, project: project) }
let(:test_case_keys) { [tc.key_hash] }
context 'when unit test failures are not within the date range but are for the unit test keys' do
let(:test) { create(:ci_unit_test, project: project) }
let(:unit_test_keys) { [test.key_hash] }
 
before do
create(:ci_test_case_failure, test_case: tc, failed_at: 15.days.ago)
create(:ci_unit_test_failure, unit_test: test, failed_at: 15.days.ago)
end
 
it 'excludes them from the count' do
expect(recent_failures[tc.key_hash]).to be_nil
expect(recent_failures[test.key_hash]).to be_nil
end
end
end
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::UnitTest do
describe 'relationships' do
it { is_expected.to belong_to(:project) }
it { is_expected.to have_many(:unit_test_failures) }
end
describe 'validations' do
subject { build(:ci_unit_test) }
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_presence_of(:key_hash) }
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_presence_of(:suite_name) }
end
describe '.find_or_create_by_batch' do
let(:project) { create(:project) }
it 'finds or creates records for the given unit test keys', :aggregate_failures do
existing_test = create(:ci_unit_test, project: project, suite_name: 'rspec', name: 'Math#sum adds numbers')
new_key = Digest::SHA256.hexdigest(SecureRandom.hex)
attrs = [
{
key_hash: existing_test.key_hash,
name: 'This new name will not apply',
suite_name: 'This new suite name will not apply'
},
{
key_hash: new_key,
name: 'Component works',
suite_name: 'jest'
}
]
result = described_class.find_or_create_by_batch(project, attrs)
expect(result).to match_array([
have_attributes(
key_hash: existing_test.key_hash,
suite_name: 'rspec',
name: 'Math#sum adds numbers'
),
have_attributes(
key_hash: new_key,
suite_name: 'jest',
name: 'Component works'
)
])
expect(result).to all(be_persisted)
end
context 'when a given name or suite_name exceeds the string size limit' do
before do
stub_const("#{described_class}::MAX_NAME_SIZE", 6)
stub_const("#{described_class}::MAX_SUITE_NAME_SIZE", 6)
end
it 'truncates the values before storing the information' do
new_key = Digest::SHA256.hexdigest(SecureRandom.hex)
attrs = [
{
key_hash: new_key,
name: 'abcdefg',
suite_name: 'abcdefg'
}
]
result = described_class.find_or_create_by_batch(project, attrs)
expect(result).to match_array([
have_attributes(
key_hash: new_key,
suite_name: 'abc...',
name: 'abc...'
)
])
expect(result).to all(be_persisted)
end
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment