diff --git a/backend/core/models/domainlayer/qa/qa_test_case_execution.go b/backend/core/models/domainlayer/qa/qa_test_case_execution.go index cfab89b6d05..aaf237b6fce 100644 --- a/backend/core/models/domainlayer/qa/qa_test_case_execution.go +++ b/backend/core/models/domainlayer/qa/qa_test_case_execution.go @@ -33,6 +33,7 @@ type QaTestCaseExecution struct { FinishTime time.Time `gorm:"comment:Test finish time"` CreatorId string `gorm:"type:varchar(255);comment:Executor ID"` Status string `gorm:"type:varchar(255);comment:Test execution status | PENDING | IN_PROGRESS | SUCCESS | FAILED"` // enum, using string + IsInvalid bool } func (QaTestCaseExecution) TableName() string { diff --git a/backend/core/models/migrationscripts/20260313_add_is_invalid_to_qa_test_case_executions.go b/backend/core/models/migrationscripts/20260313_add_is_invalid_to_qa_test_case_executions.go new file mode 100644 index 00000000000..ce7656e1e4c --- /dev/null +++ b/backend/core/models/migrationscripts/20260313_add_is_invalid_to_qa_test_case_executions.go @@ -0,0 +1,52 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package migrationscripts + +import ( + "github.com/apache/incubator-devlake/core/context" + "github.com/apache/incubator-devlake/core/errors" + "github.com/apache/incubator-devlake/core/plugin" +) + +var _ plugin.MigrationScript = (*addIsInvalidToQaTestCaseExecution)(nil) + +type qaTestCaseExecution20260313 struct { + IsInvalid bool +} + +func (qaTestCaseExecution20260313) TableName() string { + return "qa_test_case_executions" +} + +type addIsInvalidToQaTestCaseExecution struct{} + +func (*addIsInvalidToQaTestCaseExecution) Up(basicRes context.BasicRes) errors.Error { + db := basicRes.GetDal() + if err := db.AutoMigrate(&qaTestCaseExecution20260313{}); err != nil { + return err + } + return nil +} + +func (*addIsInvalidToQaTestCaseExecution) Version() uint64 { + return 20260313100000 +} + +func (*addIsInvalidToQaTestCaseExecution) Name() string { + return "add is_invalid to qa_test_case_executions" +} diff --git a/backend/core/models/migrationscripts/register.go b/backend/core/models/migrationscripts/register.go index 5b682b66222..9372d8fbd02 100644 --- a/backend/core/models/migrationscripts/register.go +++ b/backend/core/models/migrationscripts/register.go @@ -136,6 +136,7 @@ func All() []plugin.MigrationScript { new(addCqIssueImpacts), new(addDueDateToIssues), new(createQaTables), + new(addIsInvalidToQaTestCaseExecution), new(increaseCqIssueComponentLength), new(extendFieldSizeForCq), new(addIssueFixVerion), diff --git a/backend/plugins/customize/e2e/import_test_case_execution_test.go b/backend/plugins/customize/e2e/import_test_case_execution_test.go index 92d5750b86b..a74c69940a6 100644 --- a/backend/plugins/customize/e2e/import_test_case_execution_test.go +++ b/backend/plugins/customize/e2e/import_test_case_execution_test.go @@ -71,6 +71,7 @@ func TestImportQaTestCaseExecutionsDataFlow(t *testing.T) { "start_time", "finish_time", "creator_id", + "is_invalid", "status", }) dataflowTester.VerifyTableWithRawData( @@ -104,6 +105,7 @@ func TestImportQaTestCaseExecutionsDataFlow(t *testing.T) { "start_time", "finish_time", "creator_id", + "is_invalid", "status", }) @@ -117,3 +119,51 @@ func TestImportQaTestCaseExecutionsDataFlow(t *testing.T) { }, ) } + +// TestImportQaTestCaseExecutions_NoIsInvalidColumn tests backward compatibility: +// Verifies that importing CSV files without the is_invalid column works correctly, +// and the is_invalid field defaults to false. +func TestImportQaTestCaseExecutions_NoIsInvalidColumn(t *testing.T) { + var plugin impl.Customize + dataflowTester := e2ehelper.NewDataFlowTester(t, "customize", plugin) + + // Flush the relevant table + dataflowTester.FlushTabler(&qa.QaTestCaseExecution{}) + dataflowTester.FlushTabler(&crossdomain.Account{}) + + // Create a new service instance + svc := service.NewService(dataflowTester.Dal) + + // Use the existing CSV file that does NOT contain is_invalid column + // This simulates backward compatibility with old CSV files + qaTestCaseExecutionsFile, err := os.Open("raw_tables/qa_test_case_executions_input.csv") + if err != nil { + t.Fatal(err) + } + defer qaTestCaseExecutionsFile.Close() + + // Define a dummy qaProjectId + qaProjectId := "test-backward-compat-project" + + // Import data from the CSV file (which has no is_invalid column) + err = svc.ImportQaTestCaseExecutions(qaProjectId, qaTestCaseExecutionsFile, false) + if err != nil { + t.Fatalf("ImportQaTestCaseExecutions failed: %v", err) + } + + // Verify the imported data has is_invalid defaulted to false + dataflowTester.VerifyTableWithRawData( + &qa.QaTestCaseExecution{}, + "snapshot_tables/qa_test_case_executions_output_no_is_invalid_column.csv", + []string{ + "id", + "qa_project_id", + "qa_test_case_id", + "create_time", + "start_time", + "finish_time", + "creator_id", + "is_invalid", + "status", + }) +} diff --git a/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output.csv b/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output.csv index 1d51d4a0d66..cd78e9ec52e 100644 --- a/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output.csv +++ b/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output.csv @@ -1,4 +1,4 @@ -id,qa_project_id,qa_test_case_id,create_time,start_time,finish_time,creator_id,status,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -exec-1,test-qa-project-id,tc-1,2023-03-01T10:00:00.000+00:00,2023-03-01T10:01:00.000+00:00,2023-03-01T10:05:00.000+00:00,csv:CsvAccount:0:user-a,SUCCESS,test-qa-project-id,,, -exec-2,test-qa-project-id,tc-2,2023-03-01T11:00:00.000+00:00,2023-03-01T11:02:00.000+00:00,2023-03-01T11:06:00.000+00:00,csv:CsvAccount:0:user-b,FAILED,test-qa-project-id,,, -exec-3,test-qa-project-id,tc-1,2023-03-02T10:00:00.000+00:00,2023-03-02T10:01:00.000+00:00,2023-03-02T10:04:00.000+00:00,csv:CsvAccount:0:user-a,SUCCESS,test-qa-project-id,,, +id,qa_project_id,qa_test_case_id,create_time,start_time,finish_time,creator_id,is_invalid,status,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark +exec-1,test-qa-project-id,tc-1,2023-03-01T10:00:00.000+00:00,2023-03-01T10:01:00.000+00:00,2023-03-01T10:05:00.000+00:00,csv:CsvAccount:0:user-a,0,SUCCESS,test-qa-project-id,,, +exec-2,test-qa-project-id,tc-2,2023-03-01T11:00:00.000+00:00,2023-03-01T11:02:00.000+00:00,2023-03-01T11:06:00.000+00:00,csv:CsvAccount:0:user-b,0,FAILED,test-qa-project-id,,, +exec-3,test-qa-project-id,tc-1,2023-03-02T10:00:00.000+00:00,2023-03-02T10:01:00.000+00:00,2023-03-02T10:04:00.000+00:00,csv:CsvAccount:0:user-a,0,SUCCESS,test-qa-project-id,,, diff --git a/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output_incremental.csv b/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output_incremental.csv index e214d734b23..90e496a27bd 100644 --- a/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output_incremental.csv +++ b/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output_incremental.csv @@ -1,5 +1,5 @@ -id,qa_project_id,qa_test_case_id,create_time,start_time,finish_time,creator_id,status,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark -exec-1,test-qa-project-id,tc-1,2023-03-04T10:00:00.000+00:00,2023-03-04T10:01:00.000+00:00,2023-03-04T10:06:00.000+00:00,csv:CsvAccount:0:user-a,FAILED,test-qa-project-id,,, -exec-2,test-qa-project-id,tc-2,2023-03-01T11:00:00.000+00:00,2023-03-01T11:02:00.000+00:00,2023-03-01T11:06:00.000+00:00,csv:CsvAccount:0:user-b,FAILED,test-qa-project-id,,, -exec-3,test-qa-project-id,tc-1,2023-03-02T10:00:00.000+00:00,2023-03-02T10:01:00.000+00:00,2023-03-02T10:04:00.000+00:00,csv:CsvAccount:0:user-a,SUCCESS,test-qa-project-id,,, -exec-4,test-qa-project-id,tc-3,2023-03-03T10:00:00.000+00:00,2023-03-03T10:01:00.000+00:00,2023-03-03T10:05:00.000+00:00,csv:CsvAccount:0:user-c,SUCCESS,test-qa-project-id,,, +id,qa_project_id,qa_test_case_id,create_time,start_time,finish_time,creator_id,is_invalid,status,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark +exec-1,test-qa-project-id,tc-1,2023-03-04T10:00:00.000+00:00,2023-03-04T10:01:00.000+00:00,2023-03-04T10:06:00.000+00:00,csv:CsvAccount:0:user-a,0,FAILED,test-qa-project-id,,, +exec-2,test-qa-project-id,tc-2,2023-03-01T11:00:00.000+00:00,2023-03-01T11:02:00.000+00:00,2023-03-01T11:06:00.000+00:00,csv:CsvAccount:0:user-b,0,FAILED,test-qa-project-id,,, +exec-3,test-qa-project-id,tc-1,2023-03-02T10:00:00.000+00:00,2023-03-02T10:01:00.000+00:00,2023-03-02T10:04:00.000+00:00,csv:CsvAccount:0:user-a,0,SUCCESS,test-qa-project-id,,, +exec-4,test-qa-project-id,tc-3,2023-03-03T10:00:00.000+00:00,2023-03-03T10:01:00.000+00:00,2023-03-03T10:05:00.000+00:00,csv:CsvAccount:0:user-c,0,SUCCESS,test-qa-project-id,,, diff --git a/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output_no_is_invalid_column.csv b/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output_no_is_invalid_column.csv new file mode 100644 index 00000000000..e313377a0c5 --- /dev/null +++ b/backend/plugins/customize/e2e/snapshot_tables/qa_test_case_executions_output_no_is_invalid_column.csv @@ -0,0 +1,4 @@ +id,qa_project_id,qa_test_case_id,create_time,start_time,finish_time,creator_id,is_invalid,status,_raw_data_params,_raw_data_table,_raw_data_id,_raw_data_remark +exec-1,test-backward-compat-project,tc-1,2023-03-01T10:00:00.000+00:00,2023-03-01T10:01:00.000+00:00,2023-03-01T10:05:00.000+00:00,csv:CsvAccount:0:user-a,0,SUCCESS,test-backward-compat-project,,, +exec-2,test-backward-compat-project,tc-2,2023-03-01T11:00:00.000+00:00,2023-03-01T11:02:00.000+00:00,2023-03-01T11:06:00.000+00:00,csv:CsvAccount:0:user-b,0,FAILED,test-backward-compat-project,,, +exec-3,test-backward-compat-project,tc-1,2023-03-02T10:00:00.000+00:00,2023-03-02T10:01:00.000+00:00,2023-03-02T10:04:00.000+00:00,csv:CsvAccount:0:user-a,0,SUCCESS,test-backward-compat-project,,, \ No newline at end of file diff --git a/backend/plugins/customize/service/service.go b/backend/plugins/customize/service/service.go index 89e8833cf1c..5ef3bcbb3bb 100644 --- a/backend/plugins/customize/service/service.go +++ b/backend/plugins/customize/service/service.go @@ -541,6 +541,10 @@ func (s *Service) qaTestCaseExecutionHandler(qaProjectId string) func(record map } delete(record, "creator_name") record["qa_project_id"] = qaProjectId + // Set default value for is_invalid if not present or empty in the CSV + if isInvalid, exists := record["is_invalid"]; !exists || isInvalid == "" { + record["is_invalid"] = false + } return s.dal.CreateWithMap(&qa.QaTestCaseExecution{}, record) } }