meteologica/service_a/internal/domains/meteo/file_test.go

146 lines
4.6 KiB
Go

package meteo_test
import (
"os"
"servicea/internal/domains/meteo"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func Test_CSV_ParseFile(t *testing.T) {
tests := []struct {
name string
filePath string
expectedInserted int
expectedRejected int
validateInserted func(t *testing.T, inserted []meteo.MeteoData)
validateRejected func(t *testing.T, rejected []meteo.RejectedMeteoData)
}{
{
name: "valid record",
filePath: "./../../../assets/test_1.csv",
expectedInserted: 1,
expectedRejected: 0,
validateInserted: func(t *testing.T, inserted []meteo.MeteoData) {
assert.Equal(t, 1, len(inserted))
record := inserted[0]
assert.Equal(t, time.Date(2025, 10, 12, 0, 0, 0, 0, time.UTC), record.Timestamp)
assert.Equal(t, "Madrid", record.Location)
assert.Equal(t, float32(11.55), record.MaxTemp)
assert.Equal(t, float32(6.25), record.MinTemp)
assert.Equal(t, float32(0), record.Rainfall)
assert.Equal(t, float32(10), record.Cloudiness)
},
validateRejected: func(t *testing.T, rejected []meteo.RejectedMeteoData) {
assert.Empty(t, rejected)
},
},
{
name: "record with leading spaces",
filePath: "./../../../assets/test_2.csv",
expectedInserted: 1,
expectedRejected: 0,
validateInserted: func(t *testing.T, inserted []meteo.MeteoData) {
assert.Equal(t, 1, len(inserted))
assert.Equal(t, "Madrid", inserted[0].Location)
},
validateRejected: func(t *testing.T, rejected []meteo.RejectedMeteoData) {
assert.Empty(t, rejected)
},
},
{
name: "missing city column",
filePath: "./../../../assets/test_3.csv",
expectedInserted: 0,
expectedRejected: 1,
validateInserted: func(t *testing.T, inserted []meteo.MeteoData) {
assert.Empty(t, inserted)
},
validateRejected: func(t *testing.T, rejected []meteo.RejectedMeteoData) {
assert.Equal(t, 1, len(rejected))
assert.Contains(t, rejected[0].Reason, "missing or invalid city field")
assert.Equal(t, "2025/10/12;11,55;6,25;0;10", rejected[0].RowValue)
},
},
{
name: "empty file with only header",
filePath: "./../../../assets/test_4.csv",
expectedInserted: 0,
expectedRejected: 0,
validateInserted: func(t *testing.T, inserted []meteo.MeteoData) {
assert.Empty(t, inserted)
},
validateRejected: func(t *testing.T, rejected []meteo.RejectedMeteoData) {
assert.Empty(t, rejected)
},
},
{
name: "missing max temp field value",
filePath: "./../../../assets/test_5.csv",
expectedInserted: 0,
expectedRejected: 1,
validateInserted: func(t *testing.T, inserted []meteo.MeteoData) {
assert.Empty(t, inserted)
},
validateRejected: func(t *testing.T, rejected []meteo.RejectedMeteoData) {
assert.Equal(t, 1, len(rejected))
assert.Contains(t, rejected[0].Reason, "missing or invalid max temp field")
assert.Equal(t, "2025/10/12;Madrid;;6,25;0;10", rejected[0].RowValue)
},
},
{
name: "missing city field value",
filePath: "./../../../assets/test_6.csv",
expectedInserted: 0,
expectedRejected: 1,
validateInserted: func(t *testing.T, inserted []meteo.MeteoData) {
assert.Empty(t, inserted)
},
validateRejected: func(t *testing.T, rejected []meteo.RejectedMeteoData) {
assert.Equal(t, 1, len(rejected))
assert.Contains(t, rejected[0].Reason, "missing or invalid city field")
assert.Equal(t, "2025/10/12;;11,55;6,25;0;10", rejected[0].RowValue)
},
},
{
name: "missing date field value",
filePath: "./../../../assets/test_7.csv",
expectedInserted: 0,
expectedRejected: 1,
validateInserted: func(t *testing.T, inserted []meteo.MeteoData) {
assert.Empty(t, inserted)
},
validateRejected: func(t *testing.T, rejected []meteo.RejectedMeteoData) {
assert.Equal(t, 1, len(rejected))
assert.Contains(t, rejected[0].Reason, "missing or invalid date field")
assert.Equal(t, ";Madrid;11,55;6,25;0;10", rejected[0].RowValue)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
file, err := os.Open(tt.filePath)
assert.NoError(t, err)
defer file.Close()
csvIngest := &meteo.CSV{}
fileStats := &meteo.FileStats{}
inserted, rejected, err := csvIngest.Parse(file)
assert.NoError(t, err)
assert.Equal(t, tt.expectedInserted, fileStats.RowsInserted)
assert.Equal(t, tt.expectedRejected, fileStats.RowsRejected)
if tt.validateInserted != nil {
tt.validateInserted(t, inserted)
}
if tt.validateRejected != nil {
tt.validateRejected(t, rejected)
}
})
}
}