From d3cf96879c791abcfd3201fcb9efe0775068ed50 Mon Sep 17 00:00:00 2001 From: pasha1coil Date: Mon, 21 Jul 2025 12:13:40 +0300 Subject: [PATCH] review full, next need work with todo and configuration --- tests/main_test.go | 1050 +++++++++----------------------------------- 1 file changed, 219 insertions(+), 831 deletions(-) diff --git a/tests/main_test.go b/tests/main_test.go index c85f069..40b4c80 100644 --- a/tests/main_test.go +++ b/tests/main_test.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "gitea.pena/SQuiz/common/model" + "gitea.pena/SQuiz/common/repository/statistics" "gitea.pena/SQuiz/core/internal/controllers/http_controllers/question" "gitea.pena/SQuiz/core/internal/controllers/http_controllers/quiz" result2 "gitea.pena/SQuiz/core/internal/controllers/http_controllers/result" @@ -22,6 +23,7 @@ import ( // todo также нужно взять и сделать "константы" для тестирования результатов с ответами // todo нужно определить из кликхауса на чем будем тестировать статистику +var validQuizIDForTestingClickHouse = 21211 var PublicKey = `-----BEGIN PUBLIC KEY-----MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHgnvr7O2tiApjJfid1orFnIGm6980fZp+Lpbjo+NC/0whMFga2Biw5b1G2Q/B2u0tpO1Fs/E8z7Lv1nYfr5jx2S8x6BdA4TS2kB9Kf0wn0+7wSlyikHoKhbtzwXHZl17GsyEi6wHnsqNBSauyIWhpha8i+Y+3GyaOY536H47qyXAgMBAAE=-----END PUBLIC KEY-----` var postgresCred = "postgres://squiz:Redalert2@localhost:35432/squiz?sslmode=disable" //os.Getenv("POSTGRES_CRED") var baseURL = "http://127.0.0.1:1488" //os.Getenv("API_BASE_URL") @@ -7910,56 +7912,11 @@ func deleteResultRequest(token string, resultId string) (*http.Response, error) return http.DefaultClient.Do(req) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы +// отсмотрено func TestDeleteResult_Success(t *testing.T) { - // Создаем квиз для тестирования удаления результатов - quizResp, err := createQuizRequest(deleteResultToken, map[string]interface{}{ - "name": "Квиз для тестирования удаления результатов", - "status": "start", - }) - assert.NoError(t, err) - defer quizResp.Body.Close() + testData := createTestDataForResults(t, deleteResultToken, "Квиз для тестирования удаления результатов") - var quizResult model.Quiz - err = json.NewDecoder(quizResp.Body).Decode(&quizResult) - assert.NoError(t, err) - quizID := quizResult.Id - - // Создаем несколько вопросов для квиза - question1Resp, err := createQuestionRequest(deleteResultToken, map[string]interface{}{ - "quiz_id": quizID, - "title": "Вопрос 1 для удаления результатов", - "type": "text", - "description": "Введите ответ.", - "required": true, - "page": 1, - "content": `{"placeholder": "Введите ответ"}`, - }) - assert.NoError(t, err) - defer question1Resp.Body.Close() - - var question1Result model.Question - err = json.NewDecoder(question1Resp.Body).Decode(&question1Result) - assert.NoError(t, err) - - question2Resp, err := createQuestionRequest(deleteResultToken, map[string]interface{}{ - "quiz_id": quizID, - "title": "Вопрос 2 для удаления результатов", - "type": "variant", - "description": "Выберите ответ.", - "required": true, - "page": 1, - "content": `{"variants": ["Вариант 1", "Вариант 2", "Вариант 3"]}`, - }) - assert.NoError(t, err) - defer question2Resp.Body.Close() - - var question2Result model.Question - err = json.NewDecoder(question2Resp.Body).Decode(&question2Result) - assert.NoError(t, err) - - // Получаем результаты квиза - getResultsResp, err := getResultsRequest(deleteResultToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + getResultsResp, err := getResultsRequest(deleteResultToken, fmt.Sprintf("%v", testData.Quiz.Id), map[string]interface{}{ "Page": 0, "Limit": 10, }) @@ -7970,82 +7927,58 @@ func TestDeleteResult_Success(t *testing.T) { err = json.NewDecoder(getResultsResp.Body).Decode(&resultsData) assert.NoError(t, err) - // Если есть результаты, тестируем их удаление - if len(resultsData.Results) > 0 { - firstResult := resultsData.Results[0] - resultID := fmt.Sprintf("%v", firstResult.Id) + firstResult := resultsData.Results[0] + resultID := fmt.Sprintf("%v", firstResult.Id) - // Удаляем результат - resp, err := deleteResultRequest(deleteResultToken, resultID) - assert.NoError(t, err) - defer resp.Body.Close() + resp, err := deleteResultRequest(deleteResultToken, resultID) + assert.NoError(t, err) + defer resp.Body.Close() - assert.Equal(t, http.StatusOK, resp.StatusCode) + assert.Equal(t, http.StatusOK, resp.StatusCode) - // Проверяем, что результат действительно удален - getResultsAfterDeleteResp, err := getResultsRequest(deleteResultToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ - "Page": 0, - "Limit": 10, - }) - assert.NoError(t, err) - defer getResultsAfterDeleteResp.Body.Close() - - var resultsAfterDelete result2.ReqExportResponse - err = json.NewDecoder(getResultsAfterDeleteResp.Body).Decode(&resultsAfterDelete) - assert.NoError(t, err) - - // Проверяем, что количество результатов уменьшилось - assert.LessOrEqual(t, resultsAfterDelete.TotalCount, resultsData.TotalCount) - } else { - // Если результатов нет, тестируем удаление несуществующего результата - resp, err := deleteResultRequest(deleteResultToken, "999999") - assert.NoError(t, err) - defer resp.Body.Close() - - // Должен вернуться успешный статус (мягкое удаление) - assert.Equal(t, http.StatusOK, resp.StatusCode) - } -} - -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы -func TestDeleteResult_Idempotency(t *testing.T) { - createResp, err := createQuizRequest(deleteResultToken, map[string]interface{}{ - "name": "Квиз для идемпотентности удаления результатов", - "status": "start", + getResultsAfterDeleteResp, err := getResultsRequest(deleteResultToken, fmt.Sprintf("%v", testData.Quiz.Id), map[string]interface{}{ + "Page": 0, + "Limit": 10, }) assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] + defer getResultsAfterDeleteResp.Body.Close() - getResultsResp, err := getResultsRequest(deleteResultToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ - "Page": 1, + var resultsAfterDelete result2.ReqExportResponse + err = json.NewDecoder(getResultsAfterDeleteResp.Body).Decode(&resultsAfterDelete) + assert.NoError(t, err) + + assert.LessOrEqual(t, resultsAfterDelete.TotalCount, resultsData.TotalCount) +} + +// todo +func TestDeleteResult_Idempotency(t *testing.T) { + testData := createTestDataForResults(t, deleteResultToken, "Квиз для идемпотентности удаления результатов") + + getResultsResp, err := getResultsRequest(deleteResultToken, fmt.Sprintf("%v", testData.Quiz.Id), map[string]interface{}{ + "Page": 0, "Limit": 5, }) assert.NoError(t, err) defer getResultsResp.Body.Close() - var resultsData map[string]interface{} + var resultsData result2.ReqExportResponse err = json.NewDecoder(getResultsResp.Body).Decode(&resultsData) assert.NoError(t, err) - //results := resultsData["results"].([]interface{}) - // - //if len(results) > 0 { - // firstResult := results[0].(map[string]interface{}) - // resultID := fmt.Sprintf("%v", firstResult["id"]) - // - // resp1, err := deleteResultRequest(deleteResultToken, resultID) - // assert.NoError(t, err) - // defer resp1.Body.Close() - // assert.Equal(t, http.StatusOK, resp1.StatusCode) - // - // resp2, err := deleteResultRequest(deleteResultToken, resultID) - // assert.NoError(t, err) - // defer resp2.Body.Close() - // assert.Equal(t, http.StatusOK, resp2.StatusCode) - //} + + if len(resultsData.Results) > 0 { + firstResult := resultsData.Results[0] + resultID := fmt.Sprintf("%v", firstResult.Id) + + resp1, err := deleteResultRequest(deleteResultToken, resultID) + assert.NoError(t, err) + defer resp1.Body.Close() + assert.Equal(t, http.StatusOK, resp1.StatusCode) + + resp2, err := deleteResultRequest(deleteResultToken, resultID) + assert.NoError(t, err) + defer resp2.Body.Close() + assert.Equal(t, http.StatusOK, resp2.StatusCode) + } } // отсмотрено @@ -8084,77 +8017,7 @@ func TestDeleteResult_InputValidation(t *testing.T) { }) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы -func TestDeleteResult_Performance(t *testing.T) { - createResp, err := createQuizRequest(deleteResultToken, map[string]interface{}{ - "name": "Квиз для теста производительности удаления результатов", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - - getResultsResp, err := getResultsRequest(deleteResultToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ - "Page": 1, - "Limit": 10, - }) - assert.NoError(t, err) - defer getResultsResp.Body.Close() - - var resultsData map[string]interface{} - err = json.NewDecoder(getResultsResp.Body).Decode(&resultsData) - assert.NoError(t, err) - //results := resultsData["results"].([]interface{}) - // - //if len(results) > 0 { - // firstResult := results[0].(map[string]interface{}) - // resultID := fmt.Sprintf("%v", firstResult["id"]) - // - // t.Run("ResponseTime", func(t *testing.T) { - // start := time.Now() - // resp, err := deleteResultRequest(deleteResultToken, resultID) - // duration := time.Since(start) - // - // assert.NoError(t, err) - // defer resp.Body.Close() - // assert.Less(t, duration.Milliseconds(), int64(500)) - // }) - //} - - t.Run("BulkDelete", func(t *testing.T) { - getMoreResultsResp, err := getResultsRequest(deleteResultToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ - "Page": 1, - "Limit": 20, - }) - assert.NoError(t, err) - defer getMoreResultsResp.Body.Close() - - var moreResultsData map[string]interface{} - err = json.NewDecoder(getMoreResultsResp.Body).Decode(&moreResultsData) - assert.NoError(t, err) - //moreResults := moreResultsData["results"].([]interface{}) - // - //var wg sync.WaitGroup - //for i := 0; i < len(moreResults) && i < 5; i++ { - // wg.Add(1) - // go func(result interface{}) { - // defer wg.Done() - // resultMap := result.(map[string]interface{}) - // resultID := fmt.Sprintf("%v", resultMap["id"]) - // resp, err := deleteResultRequest(deleteResultToken, resultID) - // if err == nil && resp != nil { - // resp.Body.Close() - // } - // }(moreResults[i]) - //} - //wg.Wait() - }) -} - -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы +// отсмотрено func TestDeleteResult_BoundaryCases(t *testing.T) { t.Run("VeryLongResultID", func(t *testing.T) { longID := make([]byte, 1025) @@ -8175,27 +8038,6 @@ func TestDeleteResult_BoundaryCases(t *testing.T) { }) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы -func TestDeleteResult_ErrorHandling(t *testing.T) { - t.Run("MalformedRequest", func(t *testing.T) { - req, err := http.NewRequest("DELETE", baseURL+"/results/invalid-id", bytes.NewReader([]byte("invalid_body"))) - assert.NoError(t, err) - req.Header.Set("Authorization", "Bearer "+deleteResultToken) - req.Header.Set("Content-Type", "application/json") - resp, err := http.DefaultClient.Do(req) - assert.NoError(t, err) - defer resp.Body.Close() - assert.NotEqual(t, http.StatusOK, resp.StatusCode) - }) - - t.Run("ServerError", func(t *testing.T) { - resp, err := deleteResultRequest(deleteResultToken, "invalid-id") - assert.NoError(t, err) - defer resp.Body.Close() - assert.NotEqual(t, http.StatusOK, resp.StatusCode) - }) -} - func updateResultsStatusRequest(token string, body map[string]interface{}) (*http.Response, error) { payload, err := json.Marshal(body) if err != nil { @@ -8210,56 +8052,11 @@ func updateResultsStatusRequest(token string, body map[string]interface{}) (*htt return http.DefaultClient.Do(req) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы +// отсмотрено func TestUpdateResultsStatus_Success(t *testing.T) { - // Создаем квиз для тестирования обновления статуса результатов - quizResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для тестирования обновления статуса результатов", - "status": "start", - }) - assert.NoError(t, err) - defer quizResp.Body.Close() + testData := createTestDataForResults(t, validToken, "Квиз для тестирования обновления статуса результатов") - var quizResult model.Quiz - err = json.NewDecoder(quizResp.Body).Decode(&quizResult) - assert.NoError(t, err) - quizID := quizResult.Id - - // Создаем несколько вопросов для квиза - question1Resp, err := createQuestionRequest(validToken, map[string]interface{}{ - "quiz_id": quizID, - "title": "Вопрос 1 для обновления статуса", - "type": "text", - "description": "Введите ответ.", - "required": true, - "page": 1, - "content": `{"placeholder": "Введите ответ"}`, - }) - assert.NoError(t, err) - defer question1Resp.Body.Close() - - var question1Result model.Question - err = json.NewDecoder(question1Resp.Body).Decode(&question1Result) - assert.NoError(t, err) - - question2Resp, err := createQuestionRequest(validToken, map[string]interface{}{ - "quiz_id": quizID, - "title": "Вопрос 2 для обновления статуса", - "type": "variant", - "description": "Выберите ответ.", - "required": true, - "page": 1, - "content": `{"variants": ["Вариант 1", "Вариант 2", "Вариант 3"]}`, - }) - assert.NoError(t, err) - defer question2Resp.Body.Close() - - var question2Result model.Question - err = json.NewDecoder(question2Resp.Body).Decode(&question2Result) - assert.NoError(t, err) - - // Получаем результаты квиза - getResultsResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + getResultsResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", testData.Quiz.Id), map[string]interface{}{ "Page": 0, "Limit": 10, }) @@ -8270,14 +8067,12 @@ func TestUpdateResultsStatus_Success(t *testing.T) { err = json.NewDecoder(getResultsResp.Body).Decode(&resultsData) assert.NoError(t, err) - // Если есть результаты, тестируем обновление их статуса if len(resultsData.Results) >= 2 { var answerIDs []int64 for i := 0; i < 2 && i < len(resultsData.Results); i++ { answerIDs = append(answerIDs, int64(resultsData.Results[i].Id)) } - // Обновляем статус результатов resp, err := updateResultsStatusRequest(validToken, map[string]interface{}{ "Answers": answerIDs, }) @@ -8286,8 +8081,7 @@ func TestUpdateResultsStatus_Success(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) - // Проверяем, что статус действительно обновлен - getResultsAfterUpdateResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + getResultsAfterUpdateResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", testData.Quiz.Id), map[string]interface{}{ "Page": 0, "Limit": 10, }) @@ -8298,7 +8092,6 @@ func TestUpdateResultsStatus_Success(t *testing.T) { err = json.NewDecoder(getResultsAfterUpdateResp.Body).Decode(&resultsAfterUpdate) assert.NoError(t, err) - // Проверяем, что обновленные результаты больше не помечены как новые for _, answerID := range answerIDs { for _, result := range resultsAfterUpdate.Results { if result.Id == uint64(answerID) { @@ -8306,16 +8099,6 @@ func TestUpdateResultsStatus_Success(t *testing.T) { } } } - } else { - // Если результатов нет, тестируем обновление статуса несуществующих результатов - resp, err := updateResultsStatusRequest(validToken, map[string]interface{}{ - "Answers": []int64{999999, 999998}, - }) - assert.NoError(t, err) - defer resp.Body.Close() - - // Должен вернуться статус NotAcceptable, так как у пользователя нет прав на эти результаты - assert.Equal(t, http.StatusNotAcceptable, resp.StatusCode) } } @@ -8345,15 +8128,16 @@ func TestUpdateResultsStatus_Auth(t *testing.T) { }) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы +// отсмотрено func TestUpdateResultsStatus_InputValidation(t *testing.T) { + // todo check len t.Run("MissingAnswers", func(t *testing.T) { resp, err := updateResultsStatusRequest(validToken, map[string]interface{}{}) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) - + // todo check len t.Run("EmptyAnswers", func(t *testing.T) { resp, err := updateResultsStatusRequest(validToken, map[string]interface{}{ "Answers": []int64{}, @@ -8378,145 +8162,81 @@ func TestUpdateResultsStatus_InputValidation(t *testing.T) { }) assert.NoError(t, err) defer resp.Body.Close() - assert.Equal(t, http.StatusOK, resp.StatusCode) // Идемпотентность + assert.Equal(t, http.StatusNotAcceptable, resp.StatusCode) }) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы +// отсмотрено func TestUpdateResultsStatus_Idempotency(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для идемпотентности обновления статуса", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - - getResultsResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ - "Page": 1, + testData := createTestDataForResults(t, validToken, "Квиз для идемпотентности обновления статуса") + getResultsResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", testData.Quiz.Id), map[string]interface{}{ + "Page": 0, "Limit": 5, }) assert.NoError(t, err) defer getResultsResp.Body.Close() - var resultsData map[string]interface{} + var resultsData result2.ReqExportResponse err = json.NewDecoder(getResultsResp.Body).Decode(&resultsData) assert.NoError(t, err) - //results := resultsData["results"].([]interface{}) - // - //if len(results) >= 2 { - // var answerIDs []int64 - // for i := 0; i < 2; i++ { - // result := results[i].(map[string]interface{}) - // answerIDs = append(answerIDs, int64(result["id"].(float64))) - // } - // - // resp1, err := updateResultsStatusRequest(validToken, map[string]interface{}{ - // "Answers": answerIDs, - // }) - // assert.NoError(t, err) - // defer resp1.Body.Close() - // assert.Equal(t, http.StatusOK, resp1.StatusCode) - // - // resp2, err := updateResultsStatusRequest(validToken, map[string]interface{}{ - // "Answers": answerIDs, - // }) - // assert.NoError(t, err) - // defer resp2.Body.Close() - // assert.Equal(t, http.StatusOK, resp2.StatusCode) - //} -} + results := resultsData.Results -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы -func TestUpdateResultsStatus_Performance(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для теста производительности обновления статуса", - "status": "start", + var answerIDs []uint64 + for i := 0; i < 2; i++ { + result := results[i] + answerIDs = append(answerIDs, result.Id) + } + + resp1, err := updateResultsStatusRequest(validToken, map[string]interface{}{ + "Answers": answerIDs, }) assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] + defer resp1.Body.Close() + assert.Equal(t, http.StatusOK, resp1.StatusCode) - getResultsResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ - "Page": 1, + resp2, err := updateResultsStatusRequest(validToken, map[string]interface{}{ + "Answers": answerIDs, + }) + assert.NoError(t, err) + defer resp2.Body.Close() + assert.Equal(t, http.StatusOK, resp2.StatusCode) + +} + +// отсмотрено +func TestUpdateResultsStatus_Performance(t *testing.T) { + testData := createTestDataForResults(t, validToken, "Квиз для теста производительности обновления статуса") + getResultsResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", testData.Quiz.Id), map[string]interface{}{ + "Page": 0, "Limit": 20, }) assert.NoError(t, err) defer getResultsResp.Body.Close() - var resultsData map[string]interface{} + var resultsData result2.ReqExportResponse err = json.NewDecoder(getResultsResp.Body).Decode(&resultsData) assert.NoError(t, err) - //results := resultsData["results"].([]interface{}) - // - //if len(results) > 0 { - // var answerIDs []int64 - // for i := 0; i < len(results) && i < 10; i++ { - // result := results[i].(map[string]interface{}) - // answerIDs = append(answerIDs, int64(result["id"].(float64))) - // } - // - // t.Run("ResponseTime", func(t *testing.T) { - // start := time.Now() - // resp, err := updateResultsStatusRequest(validToken, map[string]interface{}{ - // "Answers": answerIDs, - // }) - // duration := time.Since(start) - // - // assert.NoError(t, err) - // defer resp.Body.Close() - // assert.Less(t, duration.Milliseconds(), int64(500)) - // }) - // - // t.Run("LargeBatch", func(t *testing.T) { - // largeBatch := make([]int64, 100) - // for i := 0; i < 100; i++ { - // largeBatch[i] = int64(1000000 + i) // Используем несуществующие ID - // } - // - // resp, err := updateResultsStatusRequest(validToken, map[string]interface{}{ - // "Answers": largeBatch, - // }) - // assert.NoError(t, err) - // defer resp.Body.Close() - // assert.Equal(t, http.StatusOK, resp.StatusCode) - // }) - //} -} -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы -func TestUpdateResultsStatus_BoundaryCases(t *testing.T) { - t.Run("VeryLargeAnswersArray", func(t *testing.T) { - largeAnswers := make([]int64, 10000) - for i := 0; i < 10000; i++ { - largeAnswers[i] = int64(1000000 + i) - } + var answerIDs []uint64 + for i := 0; i < len(resultsData.Results) && i < 10; i++ { + result := resultsData.Results[i] + answerIDs = append(answerIDs, result.Id) + } + t.Run("ResponseTime", func(t *testing.T) { + start := time.Now() resp, err := updateResultsStatusRequest(validToken, map[string]interface{}{ - "Answers": largeAnswers, + "Answers": answerIDs, }) + duration := time.Since(start) + assert.NoError(t, err) defer resp.Body.Close() - assert.Equal(t, http.StatusOK, resp.StatusCode) - }) - - t.Run("NegativeAnswerIDs", func(t *testing.T) { - resp, err := updateResultsStatusRequest(validToken, map[string]interface{}{ - "Answers": []int64{-1, -2, -3}, - }) - assert.NoError(t, err) - defer resp.Body.Close() - assert.Equal(t, http.StatusOK, resp.StatusCode) + assert.Less(t, duration.Milliseconds(), int64(500)) }) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы +// отсмотрено func TestUpdateResultsStatus_ErrorHandling(t *testing.T) { t.Run("MalformedJSON", func(t *testing.T) { req, err := http.NewRequest("PATCH", baseURL+"/result/seen", bytes.NewReader([]byte("{invalid_json}"))) @@ -8539,19 +8259,6 @@ func TestUpdateResultsStatus_ErrorHandling(t *testing.T) { }) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы -func TestUpdateResultsStatus_SpecialCases(t *testing.T) { - t.Run("DuplicateAnswerIDs", func(t *testing.T) { - resp, err := updateResultsStatusRequest(validToken, map[string]interface{}{ - "Answers": []int64{101, 101, 102, 102, 103}, - }) - assert.NoError(t, err) - defer resp.Body.Close() - assert.Equal(t, http.StatusOK, resp.StatusCode) - }) - -} - func exportResultsRequest(token string, quizID string, body map[string]interface{}) (*http.Response, error) { payload, err := json.Marshal(body) if err != nil { @@ -8566,20 +8273,11 @@ func exportResultsRequest(token string, quizID string, body map[string]interface return http.DefaultClient.Do(req) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы +// отсмотрено func TestExportResults_Success(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для экспорта результатов", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] + testData := createTestDataForResults(t, validToken, "Квиз для экспорта результатов") - resp, err := exportResultsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := exportResultsRequest(validToken, fmt.Sprintf("%v", testData.Quiz.Id), map[string]interface{}{ "From": "2023-01-01T00:00:00Z", "To": "2023-12-31T23:59:59Z", "New": false, @@ -8621,21 +8319,12 @@ func TestExportResults_Auth(t *testing.T) { }) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы +// отсмотрено func TestExportResults_InputValidation(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для валидации экспорта", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] + testData := createTestDataForResults(t, validToken, "Квиз для валидации экспорта") t.Run("InvalidDateFormat", func(t *testing.T) { - resp, err := exportResultsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := exportResultsRequest(validToken, fmt.Sprintf("%v", testData.Quiz.Id), map[string]interface{}{ "From": "not-a-date", }) assert.NoError(t, err) @@ -8652,15 +8341,15 @@ func TestExportResults_InputValidation(t *testing.T) { defer resp.Body.Close() assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) - + // todo 404 t.Run("NonExistentQuizID", func(t *testing.T) { resp, err := exportResultsRequest(validToken, "99999", map[string]interface{}{ - "Page": 1, + "Page": 0, "Limit": 10, }) assert.NoError(t, err) defer resp.Body.Close() - assert.Equal(t, http.StatusOK, resp.StatusCode) // Возвращает пустой файл + assert.Equal(t, http.StatusNotFound, resp.StatusCode) }) } @@ -8674,59 +8363,43 @@ func getResultRequest(token string, resultID string) (*http.Response, error) { return http.DefaultClient.Do(req) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы +// отсмотрено func TestGetResult_Success(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для получения результата", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] + testData := createTestDataForResults(t, validToken, "Квиз для получения результата") - getResultsResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ - "Page": 1, + getResultsResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", testData.Quiz.Id), map[string]interface{}{ + "Page": 0, "Limit": 5, }) assert.NoError(t, err) defer getResultsResp.Body.Close() - var resultsData map[string]interface{} + var resultsData result2.ReqExportResponse err = json.NewDecoder(getResultsResp.Body).Decode(&resultsData) assert.NoError(t, err) - //results := resultsData["results"].([]interface{}) - // - //if len(results) > 0 { - // firstResult := results[0].(map[string]interface{}) - // resultID := fmt.Sprintf("%v", firstResult["id"]) - // - // resp, err := getResultRequest(validToken, resultID) - // assert.NoError(t, err) - // defer resp.Body.Close() - // - // assert.Equal(t, http.StatusOK, resp.StatusCode) - // assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) - // - // var answers []map[string]interface{} - // err = json.NewDecoder(resp.Body).Decode(&answers) - // assert.NoError(t, err) - // - // if len(answers) > 0 { - // answer := answers[0] - // assert.NotEmpty(t, answer["Id"]) - // assert.NotEmpty(t, answer["content"]) - // assert.NotEmpty(t, answer["question_id"]) - // assert.NotEmpty(t, answer["QuizId"]) - // assert.NotEmpty(t, answer["CreatedAt"]) - // assert.IsType(t, false, answer["Result"]) - // assert.IsType(t, false, answer["new"]) - // assert.IsType(t, false, answer["Deleted"]) - // assert.IsType(t, false, answer["Start"]) - // } - //} + + firstResult := resultsData.Results[0] + resultID := fmt.Sprintf("%v", firstResult.Id) + + resp, err := getResultRequest(validToken, resultID) + assert.NoError(t, err) + defer resp.Body.Close() + + assert.Equal(t, http.StatusOK, resp.StatusCode) + assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) + + var answers []model.Answer + err = json.NewDecoder(resp.Body).Decode(&answers) + assert.NoError(t, err) + + if len(answers) > 0 { + answer := answers[0] + assert.NotEmpty(t, answer.Id) + assert.NotEmpty(t, answer.Content) + assert.NotEmpty(t, answer.QuestionId) + assert.NotEmpty(t, answer.QuizId) + } + } // отсмотрено @@ -8772,48 +8445,38 @@ func TestGetResult_InputValidation(t *testing.T) { }) } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы +// отсмотрено func TestGetResult_Performance(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для теста производительности результата", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] + testData := createTestDataForResults(t, validToken, "Квиз для получения результата") - getResultsResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ - "Page": 1, + getResultsResp, err := getResultsRequest(validToken, fmt.Sprintf("%v", testData.Quiz.Id), map[string]interface{}{ + "Page": 0, "Limit": 1, }) assert.NoError(t, err) defer getResultsResp.Body.Close() - var resultsData map[string]interface{} + var resultsData result2.ReqExportResponse err = json.NewDecoder(getResultsResp.Body).Decode(&resultsData) assert.NoError(t, err) - //results := resultsData["results"].([]interface{}) - // - //if len(results) > 0 { - // firstResult := results[0].(map[string]interface{}) - // resultID := fmt.Sprintf("%v", firstResult["id"]) - // - // t.Run("ResponseTime", func(t *testing.T) { - // start := time.Now() - // resp, err := getResultRequest(validToken, resultID) - // duration := time.Since(start) - // - // assert.NoError(t, err) - // defer resp.Body.Close() - // assert.Less(t, duration.Milliseconds(), int64(500)) - // }) - //} + results := resultsData.Results + + firstResult := results[0] + resultID := fmt.Sprintf("%v", firstResult.Id) + + t.Run("ResponseTime", func(t *testing.T) { + start := time.Now() + resp, err := getResultRequest(validToken, resultID) + duration := time.Since(start) + + assert.NoError(t, err) + defer resp.Body.Close() + assert.Less(t, duration.Milliseconds(), int64(500)) + }) + } -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы +// отсмотрено func TestGetResult_BoundaryCases(t *testing.T) { t.Run("VeryLongResultID", func(t *testing.T) { longID := make([]byte, 1025) @@ -8833,32 +8496,11 @@ func TestGetResult_BoundaryCases(t *testing.T) { assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) // todo - //t.Run("SpecialCharactersInResultID", func(t *testing.T) { - // resp, err := getResultRequest(validToken, "result@#$%^&*()") - // assert.NoError(t, err) - // defer resp.Body.Close() - // assert.Equal(t, http.StatusBadRequest, resp.StatusCode) - //}) -} - -// todo для этих тестов нужно заранее заполнять бдшку ответами на вопросы -func TestGetResult_ErrorHandling(t *testing.T) { - t.Run("MalformedRequest", func(t *testing.T) { - req, err := http.NewRequest("GET", baseURL+"/result/invalid-id", bytes.NewReader([]byte("invalid_body"))) - assert.NoError(t, err) - req.Header.Set("Authorization", "Bearer "+validToken) - req.Header.Set("Content-Type", "application/json") - resp, err := http.DefaultClient.Do(req) + t.Run("SpecialCharactersInResultID", func(t *testing.T) { + resp, err := getResultRequest(validToken, "result@#$%^&*()") assert.NoError(t, err) defer resp.Body.Close() - assert.NotEqual(t, http.StatusOK, resp.StatusCode) - }) - - t.Run("ServerError", func(t *testing.T) { - resp, err := getResultRequest(validToken, "invalid-id") - assert.NoError(t, err) - defer resp.Body.Close() - assert.NotEqual(t, http.StatusOK, resp.StatusCode) + assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) } @@ -8913,30 +8555,19 @@ func TestGetDeviceStats_Success(t *testing.T) { // todo нужно заранее в кликхаусе выбрать на чем честить будем func TestGetDeviceStats_WithoutDateRange(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для статистики без диапазона дат", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - - resp, err := getDeviceStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{}) + resp, err := getDeviceStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{}) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) - var result map[string]interface{} + var result statistics.DeviceStatResp err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) - assert.NotNil(t, result["Device"]) - assert.NotNil(t, result["OS"]) - assert.NotNil(t, result["Browser"]) + assert.NotNil(t, result.Device) + assert.NotNil(t, result.OS) + assert.NotNil(t, result.Browser) } // отсмотрено @@ -8967,21 +8598,10 @@ func TestGetDeviceStats_Auth(t *testing.T) { }) } -// todo нужно заранее в кликхаусе выбрать на чем честить будем +// отсмотрено func TestGetDeviceStats_InputValidation(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для валидации статистики устройств", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - t.Run("InvalidDateFormat", func(t *testing.T) { - resp, err := getDeviceStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getDeviceStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": "not_a_timestamp", "To": time.Now().Unix(), }) @@ -9009,34 +8629,20 @@ func TestGetDeviceStats_InputValidation(t *testing.T) { defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) - var result map[string]interface{} + var result statistics.DeviceStatResp err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) - deviceStats := result["Device"].(map[string]interface{}) - osStats := result["OS"].(map[string]interface{}) - browserStats := result["Browser"].(map[string]interface{}) - assert.Empty(t, deviceStats) - assert.Empty(t, osStats) - assert.Empty(t, browserStats) + assert.Empty(t, result.Device) + assert.Empty(t, result.OS) + assert.Empty(t, result.Browser) }) } -// todo нужно заранее в кликхаусе выбрать на чем честить будем +// отсмотрено func TestGetDeviceStats_Performance(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для теста производительности статистики устройств", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - t.Run("ResponseTime", func(t *testing.T) { start := time.Now() - resp, err := getDeviceStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getDeviceStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": time.Now().Unix() - 100, "To": time.Now().Unix(), }) @@ -9053,7 +8659,7 @@ func TestGetDeviceStats_Performance(t *testing.T) { wg.Add(1) go func() { defer wg.Done() - resp, err := getDeviceStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getDeviceStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": time.Now().Unix() - 100, "To": time.Now().Unix(), }) @@ -9066,30 +8672,6 @@ func TestGetDeviceStats_Performance(t *testing.T) { }) } -// todo нужно заранее в кликхаусе выбрать на чем честить будем -func TestGetDeviceStats_ErrorHandling(t *testing.T) { - t.Run("MalformedJSON", func(t *testing.T) { - req, err := http.NewRequest("POST", baseURL+"/statistic/12345/devices", bytes.NewReader([]byte("{invalid_json}"))) - assert.NoError(t, err) - req.Header.Set("Authorization", "Bearer "+validToken) - req.Header.Set("Content-Type", "application/json") - resp, err := http.DefaultClient.Do(req) - assert.NoError(t, err) - defer resp.Body.Close() - assert.Equal(t, http.StatusBadRequest, resp.StatusCode) - }) - - t.Run("ServerError", func(t *testing.T) { - resp, err := getDeviceStatsRequest(validToken, "invalid-id", map[string]interface{}{ - "From": time.Now().Unix() - 100, - "To": time.Now().Unix(), - }) - assert.NoError(t, err) - defer resp.Body.Close() - assert.NotEqual(t, http.StatusOK, resp.StatusCode) - }) -} - func getGeneralStatsRequest(token string, quizID string, body map[string]interface{}) (*http.Response, error) { payload, err := json.Marshal(body) if err != nil { @@ -9106,18 +8688,7 @@ func getGeneralStatsRequest(token string, quizID string, body map[string]interfa // todo нужно заранее в кликхаусе выбрать на чем честить будем func TestGetGeneralStats_Success(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для общей статистики", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - - resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": time.Now().Unix() - 100, "To": time.Now().Unix(), }) @@ -9127,66 +8698,32 @@ func TestGetGeneralStats_Success(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) - var result map[string]interface{} + var result statistics.GeneralStatsResp err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) - assert.NotNil(t, result["Open"]) - assert.NotNil(t, result["Result"]) - assert.NotNil(t, result["AvTime"]) - assert.NotNil(t, result["Conversion"]) - - openStats := result["Open"].(map[string]interface{}) - resultStats := result["Result"].(map[string]interface{}) - avTimeStats := result["AvTime"].(map[string]interface{}) - conversionStats := result["Conversion"].(map[string]interface{}) - - for _, value := range openStats { - assert.IsType(t, float64(0), value) - assert.GreaterOrEqual(t, value.(float64), float64(0)) - } - for _, value := range resultStats { - assert.IsType(t, float64(0), value) - assert.GreaterOrEqual(t, value.(float64), float64(0)) - } - for _, value := range avTimeStats { - assert.IsType(t, float64(0), value) - assert.GreaterOrEqual(t, value.(float64), float64(0)) - } - for _, value := range conversionStats { - assert.IsType(t, float64(0), value) - assert.GreaterOrEqual(t, value.(float64), float64(0)) - assert.LessOrEqual(t, value.(float64), float64(100)) - } + assert.NotNil(t, result.Open) + assert.NotNil(t, result.Result) + assert.NotNil(t, result.AvTime) + assert.NotNil(t, result.Conversion) } // todo нужно заранее в кликхаусе выбрать на чем честить будем func TestGetGeneralStats_WithoutDateRange(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для общей статистики без диапазона", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - - resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{}) + resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{}) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) - var result map[string]interface{} + var result statistics.GeneralStatsResp err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) - assert.NotNil(t, result["Open"]) - assert.NotNil(t, result["Result"]) - assert.NotNil(t, result["AvTime"]) - assert.NotNil(t, result["Conversion"]) + assert.NotNil(t, result.Open) + assert.NotNil(t, result.Result) + assert.NotNil(t, result.AvTime) + assert.NotNil(t, result.Conversion) } // отсмотрено @@ -9219,19 +8756,8 @@ func TestGetGeneralStats_Auth(t *testing.T) { // todo нужно заранее в кликхаусе выбрать на чем честить будем func TestGetGeneralStats_InputValidation(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для валидации общей статистики", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - t.Run("InvalidDateFormat", func(t *testing.T) { - resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": "not_a_timestamp", "To": time.Now().Unix(), }) @@ -9259,13 +8785,13 @@ func TestGetGeneralStats_InputValidation(t *testing.T) { defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) - var result map[string]interface{} + var result statistics.GeneralStatsResp err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) - openStats := result["Open"].(map[string]interface{}) - resultStats := result["Result"].(map[string]interface{}) - avTimeStats := result["AvTime"].(map[string]interface{}) - conversionStats := result["Conversion"].(map[string]interface{}) + openStats := result.Open + resultStats := result.Result + avTimeStats := result.AvTime + conversionStats := result.Conversion assert.Empty(t, openStats) assert.Empty(t, resultStats) assert.Empty(t, avTimeStats) @@ -9275,20 +8801,9 @@ func TestGetGeneralStats_InputValidation(t *testing.T) { // todo нужно заранее в кликхаусе выбрать на чем честить будем func TestGetGeneralStats_Performance(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для теста производительности общей статистики", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - t.Run("ResponseTime", func(t *testing.T) { start := time.Now() - resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": time.Now().Unix() - 100, "To": time.Now().Unix(), }) @@ -9305,7 +8820,7 @@ func TestGetGeneralStats_Performance(t *testing.T) { wg.Add(1) go func() { defer wg.Done() - resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": time.Now().Unix() - 100, "To": time.Now().Unix(), }) @@ -9321,18 +8836,7 @@ func TestGetGeneralStats_Performance(t *testing.T) { // todo нужно заранее в кликхаусе выбрать на чем честить будем func TestGetGeneralStats_BoundaryCases(t *testing.T) { t.Run("VeryLargeDateRange", func(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для граничных случаев общей статистики", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - - resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": 0, "To": time.Now().Unix(), }) @@ -9342,24 +8846,13 @@ func TestGetGeneralStats_BoundaryCases(t *testing.T) { }) t.Run("NegativeTimestamps", func(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для отрицательных временных меток", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - - resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getGeneralStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": -1000000, "To": -500000, }) assert.NoError(t, err) defer resp.Body.Close() - assert.Equal(t, http.StatusOK, resp.StatusCode) + assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) } @@ -9379,18 +8872,7 @@ func getQuestionStatsRequest(token string, quizID string, body map[string]interf // todo нужно заранее в кликхаусе выбрать на чем честить будем func TestGetQuestionStats_Success(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для статистики вопросов", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - - resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": time.Now().Unix() - 100, "To": time.Now().Unix(), }) @@ -9400,77 +8882,30 @@ func TestGetQuestionStats_Success(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) - var result []map[string]interface{} + var result statistics.QuestionsStatsResp err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) assert.NotEmpty(t, result) + assert.NotNil(t, result.Funnel) + assert.NotNil(t, result.FunnelData) + assert.NotNil(t, result.Results) + assert.NotNil(t, result.Questions) - if len(result) > 0 { - questionStat := result[0] - - assert.NotNil(t, questionStat["Funnel"]) - assert.NotNil(t, questionStat["FunnelData"]) - assert.NotNil(t, questionStat["Results"]) - assert.NotNil(t, questionStat["Questions"]) - - funnel := questionStat["Funnel"].([]interface{}) - funnelData := questionStat["FunnelData"].([]interface{}) - results := questionStat["Results"].(map[string]interface{}) - questions := questionStat["Questions"].(map[string]interface{}) - - assert.LessOrEqual(t, len(funnel), 3) - assert.LessOrEqual(t, len(funnelData), 4) - - for _, value := range funnel { - assert.IsType(t, float64(0), value) - assert.GreaterOrEqual(t, value.(float64), float64(0)) - assert.LessOrEqual(t, value.(float64), float64(100)) - } - - for _, value := range funnelData { - assert.IsType(t, float64(0), value) - assert.GreaterOrEqual(t, value.(float64), float64(0)) - } - - for _, value := range results { - assert.IsType(t, float64(0), value) - assert.GreaterOrEqual(t, value.(float64), float64(0)) - assert.LessOrEqual(t, value.(float64), float64(100)) - } - - for _, questionData := range questions { - questionMap := questionData.(map[string]interface{}) - for _, percentage := range questionMap { - assert.IsType(t, float64(0), percentage) - assert.GreaterOrEqual(t, percentage.(float64), float64(0)) - assert.LessOrEqual(t, percentage.(float64), float64(100)) - } - } - } + assert.LessOrEqual(t, len(result.Funnel), 3) + assert.LessOrEqual(t, len(result.FunnelData), 4) } // todo нужно заранее в кликхаусе выбрать на чем честить будем func TestGetQuestionStats_WithoutDateRange(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для статистики вопросов без диапазона", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - - resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{}) + resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{}) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) - var result []map[string]interface{} + var result statistics.QuestionsStatsResp err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) assert.NotEmpty(t, result) @@ -9506,19 +8941,8 @@ func TestGetQuestionStats_Auth(t *testing.T) { // todo нужно заранее в кликхаусе выбрать на чем честить будем func TestGetQuestionStats_InputValidation(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для валидации статистики вопросов", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - t.Run("InvalidDateFormat", func(t *testing.T) { - resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": "not_a_timestamp", "To": time.Now().Unix(), }) @@ -9546,41 +8970,27 @@ func TestGetQuestionStats_InputValidation(t *testing.T) { defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) - var result []map[string]interface{} + var result statistics.QuestionsStatsResp err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) assert.NotEmpty(t, result) - if len(result) > 0 { - questionStat := result[0] - funnel := questionStat["Funnel"].([]interface{}) - funnelData := questionStat["FunnelData"].([]interface{}) - results := questionStat["Results"].(map[string]interface{}) - questions := questionStat["Questions"].(map[string]interface{}) - assert.Empty(t, funnel) - assert.Empty(t, funnelData) - assert.Empty(t, results) - assert.Empty(t, questions) - } + funnel := result.Funnel + funnelData := result.FunnelData + results := result.Results + questions := result.Questions + assert.Empty(t, funnel) + assert.Empty(t, funnelData) + assert.Empty(t, results) + assert.Empty(t, questions) }) } // todo нужно заранее в кликхаусе выбрать на чем честить будем func TestGetQuestionStats_Performance(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для теста производительности статистики вопросов", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - t.Run("ResponseTime", func(t *testing.T) { start := time.Now() - resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": time.Now().Unix() - 100, "To": time.Now().Unix(), }) @@ -9597,7 +9007,7 @@ func TestGetQuestionStats_Performance(t *testing.T) { wg.Add(1) go func() { defer wg.Done() - resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": time.Now().Unix() - 100, "To": time.Now().Unix(), }) @@ -9613,18 +9023,7 @@ func TestGetQuestionStats_Performance(t *testing.T) { // todo нужно заранее в кликхаусе выбрать на чем честить будем func TestGetQuestionStats_BoundaryCases(t *testing.T) { t.Run("VeryLargeDateRange", func(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для граничных случаев статистики вопросов", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - - resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": 0, "To": time.Now().Unix(), }) @@ -9634,24 +9033,13 @@ func TestGetQuestionStats_BoundaryCases(t *testing.T) { }) t.Run("NegativeTimestamps", func(t *testing.T) { - createResp, err := createQuizRequest(validToken, map[string]interface{}{ - "name": "Квиз для отрицательных временных меток вопросов", - "status": "start", - }) - assert.NoError(t, err) - defer createResp.Body.Close() - var createResult map[string]interface{} - err = json.NewDecoder(createResp.Body).Decode(&createResult) - assert.NoError(t, err) - quizID := createResult["id"] - - resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", quizID), map[string]interface{}{ + resp, err := getQuestionStatsRequest(validToken, fmt.Sprintf("%v", validQuizIDForTestingClickHouse), map[string]interface{}{ "From": -1000000, "To": -500000, }) assert.NoError(t, err) defer resp.Body.Close() - assert.Equal(t, http.StatusOK, resp.StatusCode) + assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) }