From 283f51fb79f8cd2da53321d234a2134ae9d8c3d4 Mon Sep 17 00:00:00 2001 From: Yehyeok Bang Date: Mon, 5 Feb 2024 19:48:31 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[#37]=20feat:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=EC=9D=98=20=ED=8F=89=EA=B7=A0=20?= =?UTF-8?q?=EC=A0=90=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/report/repositories/report_repository.go | 30 +++++++++++++++----- app/report/services/report_service.go | 13 +++++---- app/report/types/response_types.go | 13 +++++---- 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/app/report/repositories/report_repository.go b/app/report/repositories/report_repository.go index 5b039b7..f370b73 100644 --- a/app/report/repositories/report_repository.go +++ b/app/report/repositories/report_repository.go @@ -61,7 +61,7 @@ func (repo *ReportRepository) FindAll() ([]models.Report, error) { } func (repo *ReportRepository) FindRankAtAgeAndGender(user *users.User, start, end time.Time) (types.ResponseRank, error) { - var userAvgScore float64 + var userAvgScore, allAvgScore float64 var totalUsers, rank int64 ageGroup := user.Age / 10 * 10 @@ -87,6 +87,19 @@ func (repo *ReportRepository) FindRankAtAgeAndGender(user *users.User, start, en return types.ResponseRank{}, err } + // calculate average score for all users in the same age group and gender + err = repo.DB.Table("reports"). + Select("avg(score)"). + Joins("inner join users on users.id = reports.user_id"). + Where("users.age >= ? AND users.age < ?", ageGroup, ageGroup+10). + Where("users.gender = ?", user.Gender). + Where("reports.created_at BETWEEN ? AND ?", start, end). + Scan(&allAvgScore).Error + + if err != nil { + return types.ResponseRank{}, err + } + // calculate rank sql := ` SELECT COUNT(*) as rank_count @@ -110,13 +123,16 @@ func (repo *ReportRepository) FindRankAtAgeAndGender(user *users.User, start, en rank = totalUsers - rank normalRatio := fmt.Sprintf("%.2f", float64(rank)/float64(totalUsers)*100.00) + averageScore := fmt.Sprintf("%.2f", userAvgScore) + allAvgScoreStr := fmt.Sprintf("%.2f", allAvgScore) return types.ResponseRank{ - UserID: user.ID, - Nickname: user.Nickname, - Age: user.Age, - Gender: user.Gender, - NormalRatio: normalRatio, - AverageScore: userAvgScore, + UserID: user.ID, + Nickname: user.Nickname, + Age: user.Age, + Gender: user.Gender, + NormalRatio: normalRatio, + AverageScore: averageScore, + AllAverageScore: allAvgScoreStr, }, nil } diff --git a/app/report/services/report_service.go b/app/report/services/report_service.go index 3cc9a9b..1e01c5c 100644 --- a/app/report/services/report_service.go +++ b/app/report/services/report_service.go @@ -363,12 +363,13 @@ func (service *ReportService) FindRankAtAgeAndGender(c *gin.Context) (types.Resp rank, _ := service.ReportRepository.FindRankAtAgeAndGender(user, time.Now().AddDate(0, 0, -30), time.Now()) responseRank := types.ResponseRank{ - UserID: rank.UserID, - Nickname: user.Nickname, - Age: rank.Age, - Gender: rank.Gender, - NormalRatio: rank.NormalRatio, - AverageScore: rank.AverageScore, + UserID: rank.UserID, + Nickname: user.Nickname, + Age: rank.Age, + Gender: rank.Gender, + NormalRatio: rank.NormalRatio, + AverageScore: rank.AverageScore, + AllAverageScore: rank.AllAverageScore, } return responseRank, nil diff --git a/app/report/types/response_types.go b/app/report/types/response_types.go index b604f7f..37aa2d2 100644 --- a/app/report/types/response_types.go +++ b/app/report/types/response_types.go @@ -32,10 +32,11 @@ type ResponseReport struct { } type ResponseRank struct { - UserID uint `json:"user_id"` - Nickname string `json:"nickname"` - Gender string `json:"gender"` - Age int `json:"age"` - NormalRatio string `json:"normal_ratio"` - AverageScore float64 `json:"average_score"` + UserID uint `json:"user_id"` + Nickname string `json:"nickname"` + Gender string `json:"gender"` + Age int `json:"age"` + NormalRatio string `json:"normal_ratio"` + AverageScore string `json:"average_score"` + AllAverageScore string `json:"all_average_score"` } From e32553df854c85462faca3827700b71311d0d606 Mon Sep 17 00:00:00 2001 From: Yehyeok Bang Date: Mon, 5 Feb 2024 19:48:53 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[#37]=20test:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=EC=9D=98=20=ED=8F=89=EA=B7=A0=20?= =?UTF-8?q?=EC=A0=90=EC=88=98=20=EA=B4=80=EB=A0=A8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repositories/report_repository_test.go | 80 ++++++++++++++++++- app/report/services/report_service_test.go | 13 +-- 2 files changed, 86 insertions(+), 7 deletions(-) diff --git a/app/report/repositories/report_repository_test.go b/app/report/repositories/report_repository_test.go index cfeaa59..08ce8dc 100644 --- a/app/report/repositories/report_repository_test.go +++ b/app/report/repositories/report_repository_test.go @@ -632,6 +632,7 @@ func TestReportRepository_FindRankAtAgeAndGender(t *testing.T) { ageGroup := 20 userAvgScore := 80.0 + allAvgScore := 90.0 // Set up expectations for the mock DB to return the sample report mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE reports.user_id = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)"). @@ -645,6 +646,12 @@ func TestReportRepository_FindRankAtAgeAndGender(t *testing.T) { WillReturnRows(sqlmock.NewRows([]string{"count"}). AddRow("100")) + // Set up expectations for the mock DB to return average score for all users in the same age group and gender + mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE \\(users.age >= \\? AND users.age < \\?\\) AND users.gender = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)"). + WithArgs(ageGroup, ageGroup+10, user.Gender, start, end). + WillReturnRows(sqlmock.NewRows([]string{"avg"}). + AddRow(allAvgScore)) + // Set up expectations for the mock DB to return rank mock.ExpectQuery("SELECT COUNT\\(\\*\\) as rank_count FROM \\(\\s*SELECT reports.user_id, AVG\\(score\\) as average_score FROM reports INNER JOIN users\\s+on\\s+users.id = reports.user_id WHERE users.age >= \\? AND users.age < \\? AND users.gender = \\? AND reports.created_at BETWEEN \\? AND \\? GROUP BY reports.user_id\\s*\\) as subquery WHERE average_score > \\?"). WithArgs(ageGroup, ageGroup+10, user.Gender, start, end, userAvgScore). @@ -666,7 +673,8 @@ func TestReportRepository_FindRankAtAgeAndGender(t *testing.T) { assert.Equal(t, user.Age, responseRank.Age) assert.Equal(t, user.Gender, responseRank.Gender) assert.Equal(t, "80.00", responseRank.NormalRatio) - assert.Equal(t, 80.0, responseRank.AverageScore) + assert.Equal(t, "80.00", responseRank.AverageScore) + assert.Equal(t, "90.00", responseRank.AllAverageScore) } func TestReportRepository_FindRankAtAgeAndGender_Error(t *testing.T) { @@ -809,8 +817,72 @@ func TestReportRepository_FindRankAtAgeAndGender_Error3(t *testing.T) { start := time.Now().AddDate(0, 0, -30) end := time.Now() + ageGroup := 20 + + // Set up expectations for the mock DB to return the sample report + mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE reports.user_id = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)"). + WithArgs(user.ID, start, end). + WillReturnRows(sqlmock.NewRows([]string{"avg"}). + AddRow("80.0")) + + // Set up expectations for the mock DB to return total users + mock.ExpectQuery("SELECT count\\(\\*\\) FROM `users` WHERE \\(age >= \\? AND age < \\?\\) AND gender = \\?"). + WithArgs(ageGroup, ageGroup+10, user.Gender). + WillReturnRows(sqlmock.NewRows([]string{"count"}). + AddRow("100")) + + // Set up expectations for the mock DB to return average score for all users in the same age group and gender + mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE \\(users.age >= \\? AND users.age < \\?\\) AND users.gender = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)"). + WithArgs(ageGroup, ageGroup+10, user.Gender, start, end). + WillReturnError(err) + + // Call the method under test + _, err = reportRepository.FindRankAtAgeAndGender(&user, start, end) + if err == nil { + t.Fatalf("Error finding rank: %v", err) + } + + // Check that the expectations were met + assert.NoError(t, mock.ExpectationsWereMet()) +} + +func TestReportRepository_FindRankAtAgeAndGender_Error4(t *testing.T) { + // Create mock DB + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("Error creating mock DB: %v", err) + } + + // Set up expectations for the mock DB (ex: SELECT VERSION()) + mock.ExpectQuery("SELECT VERSION()"). + WillReturnRows(sqlmock.NewRows([]string{"VERSION"}). + AddRow("8.0.0")) + + // Create gorm.DB + gormDB, err := gorm.Open(mysql.New(mysql.Config{Conn: db}), &gorm.Config{}) + if err != nil { + t.Fatalf("Error creating gorm.DB: %v", err) + } + + // Create ReportRepository + reportRepository := repositories.NewReportRepository(gormDB) + + // Create sample user for the test + user := usermodel.User{ + ID: 1, + Name: "test", + Nickname: "test", + Email: "test@gmail.com", + Age: 20, + Gender: "male", + } + + start := time.Now().AddDate(0, 0, -30) + end := time.Now() + ageGroup := 20 userAvgScore := 80.0 + allAvgScore := 90.0 // Set up expectations for the mock DB to return the sample report mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE reports.user_id = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)"). @@ -824,6 +896,12 @@ func TestReportRepository_FindRankAtAgeAndGender_Error3(t *testing.T) { WillReturnRows(sqlmock.NewRows([]string{"count"}). AddRow("100")) + // Set up expectations for the mock DB to return average score for all users in the same age group and gender + mock.ExpectQuery("SELECT avg\\(score\\) FROM `reports` inner join users on users.id = reports.user_id WHERE \\(users.age >= \\? AND users.age < \\?\\) AND users.gender = \\? AND \\(reports.created_at BETWEEN \\? AND \\?\\)"). + WithArgs(ageGroup, ageGroup+10, user.Gender, start, end). + WillReturnRows(sqlmock.NewRows([]string{"avg"}). + AddRow(allAvgScore)) + // Set up expectations for the mock DB to return rank mock.ExpectQuery("SELECT COUNT\\(\\*\\) as rank_count FROM \\(\\s*SELECT reports.user_id, AVG\\(score\\) as average_score FROM reports INNER JOIN users\\s+on\\s+users.id = reports.user_id WHERE users.age >= \\? AND users.age < \\? AND users.gender = \\? AND reports.created_at BETWEEN \\? AND \\? GROUP BY reports.user_id\\s*\\) as subquery WHERE average_score > \\?"). WithArgs(ageGroup, ageGroup+10, user.Gender, start, end, userAvgScore). diff --git a/app/report/services/report_service_test.go b/app/report/services/report_service_test.go index c4ae977..7c1214e 100644 --- a/app/report/services/report_service_test.go +++ b/app/report/services/report_service_test.go @@ -832,12 +832,13 @@ func TestFindRankAtAgeAndGender(t *testing.T) { // Set up sample rank for the test rank := types.ResponseRank{ - UserID: 1, - Nickname: "test", - Age: 20, - Gender: "male", - NormalRatio: "90.00", - AverageScore: 90.000, + UserID: 1, + Nickname: "test", + Age: 20, + Gender: "male", + NormalRatio: "90.00", + AverageScore: "90.00", + AllAverageScore: "90.00", } // Set up expectations for the mock repository and util