578 lines
17 KiB
Go
578 lines
17 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"github.com/google/uuid"
|
|
"math"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap/zaptest"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
|
|
"veza-backend-api/internal/models"
|
|
)
|
|
|
|
func setupTestPlaybackABTestServiceDB(t *testing.T) (*gorm.DB, *PlaybackABTestService) {
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
require.NoError(t, err)
|
|
|
|
db.Exec("PRAGMA foreign_keys = ON")
|
|
|
|
err = db.AutoMigrate(&models.User{}, &models.Track{}, &models.PlaybackAnalytics{})
|
|
require.NoError(t, err)
|
|
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackABTestService(db, logger)
|
|
|
|
return db, service
|
|
}
|
|
|
|
func TestNewPlaybackABTestService(t *testing.T) {
|
|
db, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
logger := zaptest.NewLogger(t)
|
|
|
|
service := NewPlaybackABTestService(db, logger)
|
|
|
|
assert.NotNil(t, service)
|
|
assert.Equal(t, db, service.db)
|
|
assert.NotNil(t, service.logger)
|
|
}
|
|
|
|
func TestNewPlaybackABTestService_NilLogger(t *testing.T) {
|
|
db, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
|
|
service := NewPlaybackABTestService(db, nil)
|
|
|
|
assert.NotNil(t, service)
|
|
assert.NotNil(t, service.logger)
|
|
}
|
|
|
|
func TestPlaybackABTestService_CompareVariants_EmptyVariantNames(t *testing.T) {
|
|
_, service := setupTestPlaybackABTestServiceDB(t)
|
|
ctx := context.Background()
|
|
|
|
filterA := VariantFilter{}
|
|
filterB := VariantFilter{}
|
|
|
|
result, err := service.CompareVariants(ctx, "", "B", filterA, filterB)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "variant names cannot be empty")
|
|
assert.Nil(t, result)
|
|
|
|
result, err = service.CompareVariants(ctx, "A", "", filterA, filterB)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "variant names cannot be empty")
|
|
assert.Nil(t, result)
|
|
}
|
|
|
|
func TestPlaybackABTestService_CompareVariants_NoData(t *testing.T) {
|
|
db, service := setupTestPlaybackABTestServiceDB(t)
|
|
ctx := context.Background()
|
|
|
|
// Créer user et track
|
|
userID := uuid.New()
|
|
trackID := uuid.New()
|
|
user := &models.User{ID: userID, Username: "testuser", Slug: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
track := &models.Track{
|
|
ID: trackID,
|
|
UserID: userID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
filterA := VariantFilter{TrackID: &trackID}
|
|
filterB := VariantFilter{TrackID: &trackID}
|
|
|
|
result, err := service.CompareVariants(ctx, "A", "B", filterA, filterB)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, "A", result.VariantA.VariantName)
|
|
assert.Equal(t, "B", result.VariantB.VariantName)
|
|
assert.Equal(t, int64(0), result.VariantA.TotalSessions)
|
|
assert.Equal(t, int64(0), result.VariantB.TotalSessions)
|
|
assert.NotNil(t, result.Significance)
|
|
}
|
|
|
|
func TestPlaybackABTestService_CompareVariants_WithData(t *testing.T) {
|
|
db, service := setupTestPlaybackABTestServiceDB(t)
|
|
ctx := context.Background()
|
|
|
|
// Créer users et track
|
|
user1ID := uuid.New()
|
|
user2ID := uuid.New()
|
|
trackID := uuid.New()
|
|
user1 := &models.User{ID: user1ID, Username: "user1", Slug: "user1", Email: "user1@example.com", IsActive: true}
|
|
user2 := &models.User{ID: user2ID, Username: "user2", Slug: "user2", Email: "user2@example.com", IsActive: true}
|
|
db.Create(user1)
|
|
db.Create(user2)
|
|
track := &models.Track{
|
|
ID: trackID,
|
|
UserID: user1ID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
// Variant A: High completion
|
|
for i := 0; i < 10; i++ {
|
|
db.Create(&models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: user1ID,
|
|
PlayTime: 180,
|
|
PauseCount: 0,
|
|
SeekCount: 0,
|
|
CompletionRate: 100.0,
|
|
StartedAt: now,
|
|
CreatedAt: now,
|
|
})
|
|
}
|
|
|
|
// Variant B: Lower completion
|
|
for i := 0; i < 10; i++ {
|
|
db.Create(&models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: user2ID,
|
|
PlayTime: 90,
|
|
PauseCount: 2,
|
|
SeekCount: 1,
|
|
CompletionRate: 50.0,
|
|
StartedAt: now,
|
|
CreatedAt: now,
|
|
})
|
|
}
|
|
|
|
filterA := VariantFilter{TrackID: &trackID, UserIDs: []uuid.UUID{user1ID}}
|
|
filterB := VariantFilter{TrackID: &trackID, UserIDs: []uuid.UUID{user2ID}}
|
|
|
|
result, err := service.CompareVariants(ctx, "A", "B", filterA, filterB)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, "A", result.VariantA.VariantName)
|
|
assert.Equal(t, "B", result.VariantB.VariantName)
|
|
assert.Equal(t, int64(10), result.VariantA.TotalSessions)
|
|
assert.Equal(t, int64(10), result.VariantB.TotalSessions)
|
|
assert.Equal(t, 100.0, result.VariantA.AverageCompletion)
|
|
assert.Equal(t, 50.0, result.VariantB.AverageCompletion)
|
|
assert.NotNil(t, result.Significance)
|
|
assert.NotNil(t, result.Difference)
|
|
assert.NotNil(t, result.PercentageChange)
|
|
}
|
|
|
|
func TestPlaybackABTestService_CalculateVariantStats(t *testing.T) {
|
|
_, service := setupTestPlaybackABTestServiceDB(t)
|
|
|
|
analytics := []models.PlaybackAnalytics{
|
|
{PlayTime: 180, PauseCount: 0, SeekCount: 0, CompletionRate: 100.0},
|
|
{PlayTime: 180, PauseCount: 1, SeekCount: 0, CompletionRate: 95.0},
|
|
{PlayTime: 90, PauseCount: 2, SeekCount: 1, CompletionRate: 50.0},
|
|
}
|
|
|
|
stats := service.calculateVariantStats("TestVariant", analytics)
|
|
|
|
assert.NotNil(t, stats)
|
|
assert.Equal(t, "TestVariant", stats.VariantName)
|
|
assert.Equal(t, int64(3), stats.TotalSessions)
|
|
assert.InDelta(t, 150.0, stats.AveragePlayTime, 0.1) // (180 + 180 + 90) / 3
|
|
assert.InDelta(t, 81.67, stats.AverageCompletion, 0.1) // (100 + 95 + 50) / 3
|
|
assert.Equal(t, 1.0, stats.AveragePauses) // (0 + 1 + 2) / 3
|
|
assert.InDelta(t, 0.33, stats.AverageSeeks, 0.1) // (0 + 0 + 1) / 3
|
|
}
|
|
|
|
func TestPlaybackABTestService_CalculateVariantStats_Empty(t *testing.T) {
|
|
_, service := setupTestPlaybackABTestServiceDB(t)
|
|
|
|
analytics := []models.PlaybackAnalytics{}
|
|
stats := service.calculateVariantStats("EmptyVariant", analytics)
|
|
|
|
assert.NotNil(t, stats)
|
|
assert.Equal(t, "EmptyVariant", stats.VariantName)
|
|
assert.Equal(t, int64(0), stats.TotalSessions)
|
|
}
|
|
|
|
func TestPlaybackABTestService_CalculateStatisticalSignificance(t *testing.T) {
|
|
_, service := setupTestPlaybackABTestServiceDB(t)
|
|
|
|
// Variant A: High completion (tous à 100%)
|
|
analyticsA := []models.PlaybackAnalytics{
|
|
{CompletionRate: 100.0},
|
|
{CompletionRate: 100.0},
|
|
{CompletionRate: 100.0},
|
|
{CompletionRate: 100.0},
|
|
{CompletionRate: 100.0},
|
|
}
|
|
|
|
// Variant B: Lower completion (tous à 50%)
|
|
analyticsB := []models.PlaybackAnalytics{
|
|
{CompletionRate: 50.0},
|
|
{CompletionRate: 50.0},
|
|
{CompletionRate: 50.0},
|
|
{CompletionRate: 50.0},
|
|
{CompletionRate: 50.0},
|
|
}
|
|
|
|
significance := service.calculateStatisticalSignificance(analyticsA, analyticsB)
|
|
|
|
assert.NotNil(t, significance)
|
|
assert.GreaterOrEqual(t, significance.PValue, 0.0)
|
|
assert.LessOrEqual(t, significance.PValue, 1.0)
|
|
assert.Greater(t, significance.ConfidenceLevel, 0.0)
|
|
// EffectSize peut être 0 si les écarts-types sont 0 (toutes les valeurs identiques)
|
|
// Dans ce cas, on vérifie juste qu'il n'est pas NaN
|
|
assert.False(t, math.IsNaN(significance.EffectSize))
|
|
assert.False(t, math.IsInf(significance.EffectSize, 0))
|
|
}
|
|
|
|
func TestPlaybackABTestService_CalculateStatisticalSignificance_Empty(t *testing.T) {
|
|
_, service := setupTestPlaybackABTestServiceDB(t)
|
|
|
|
analyticsA := []models.PlaybackAnalytics{}
|
|
analyticsB := []models.PlaybackAnalytics{}
|
|
|
|
significance := service.calculateStatisticalSignificance(analyticsA, analyticsB)
|
|
|
|
assert.NotNil(t, significance)
|
|
assert.Equal(t, 1.0, significance.PValue)
|
|
assert.False(t, significance.IsSignificant)
|
|
}
|
|
|
|
func TestPlaybackABTestService_CalculateMeanAndStdDev(t *testing.T) {
|
|
_, service := setupTestPlaybackABTestServiceDB(t)
|
|
|
|
data := []float64{10.0, 20.0, 30.0, 40.0, 50.0}
|
|
mean, stdDev := service.calculateMeanAndStdDev(data)
|
|
|
|
assert.Equal(t, 30.0, mean)
|
|
assert.Greater(t, stdDev, 0.0)
|
|
}
|
|
|
|
func TestPlaybackABTestService_CalculateMeanAndStdDev_Empty(t *testing.T) {
|
|
_, service := setupTestPlaybackABTestServiceDB(t)
|
|
|
|
data := []float64{}
|
|
mean, stdDev := service.calculateMeanAndStdDev(data)
|
|
|
|
assert.Equal(t, 0.0, mean)
|
|
assert.Equal(t, 0.0, stdDev)
|
|
}
|
|
|
|
func TestPlaybackABTestService_DetermineWinner(t *testing.T) {
|
|
_, service := setupTestPlaybackABTestServiceDB(t)
|
|
|
|
statsA := &VariantStats{CompletionRate: 80.0}
|
|
statsB := &VariantStats{CompletionRate: 90.0}
|
|
significance := &StatisticalSignificance{IsSignificant: true, PValue: 0.01}
|
|
|
|
winner := service.determineWinner(statsA, statsB, significance)
|
|
assert.Equal(t, "B", winner)
|
|
|
|
// Test avec A gagnant
|
|
statsA2 := &VariantStats{CompletionRate: 90.0}
|
|
statsB2 := &VariantStats{CompletionRate: 80.0}
|
|
winner2 := service.determineWinner(statsA2, statsB2, significance)
|
|
assert.Equal(t, "A", winner2)
|
|
|
|
// Test non significatif
|
|
significance2 := &StatisticalSignificance{IsSignificant: false, PValue: 0.1}
|
|
winner3 := service.determineWinner(statsA, statsB, significance2)
|
|
assert.Equal(t, "inconclusive", winner3)
|
|
}
|
|
|
|
func TestPlaybackABTestService_GenerateRecommendation(t *testing.T) {
|
|
_, service := setupTestPlaybackABTestServiceDB(t)
|
|
|
|
statsA := &VariantStats{CompletionRate: 80.0}
|
|
statsB := &VariantStats{CompletionRate: 90.0}
|
|
significance := &StatisticalSignificance{IsSignificant: true, PValue: 0.01}
|
|
|
|
recommendation := service.generateRecommendation(statsA, statsB, significance)
|
|
assert.NotEmpty(t, recommendation)
|
|
assert.Contains(t, recommendation, "variant B")
|
|
assert.Contains(t, recommendation, "significativement meilleur")
|
|
|
|
// Test avec A gagnant
|
|
statsA2 := &VariantStats{CompletionRate: 90.0}
|
|
statsB2 := &VariantStats{CompletionRate: 80.0}
|
|
recommendation2 := service.generateRecommendation(statsA2, statsB2, significance)
|
|
assert.Contains(t, recommendation2, "variant A")
|
|
|
|
// Test non significatif
|
|
significance2 := &StatisticalSignificance{IsSignificant: false, PValue: 0.1}
|
|
recommendation3 := service.generateRecommendation(statsA, statsB, significance2)
|
|
assert.Contains(t, recommendation3, "pas statistiquement significatifs")
|
|
}
|
|
|
|
func TestPlaybackABTestService_GetAnalyticsForVariant(t *testing.T) {
|
|
db, service := setupTestPlaybackABTestServiceDB(t)
|
|
ctx := context.Background()
|
|
|
|
// Créer user et track
|
|
userID := uuid.New()
|
|
trackID := uuid.New()
|
|
user := &models.User{ID: userID, Username: "testuser", Slug: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
track := &models.Track{
|
|
ID: trackID,
|
|
UserID: userID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
analytics := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: userID,
|
|
PlayTime: 180,
|
|
PauseCount: 0,
|
|
SeekCount: 0,
|
|
CompletionRate: 100.0,
|
|
StartedAt: now,
|
|
CreatedAt: now,
|
|
}
|
|
db.Create(analytics)
|
|
|
|
filter := VariantFilter{TrackID: &trackID}
|
|
result, err := service.getAnalyticsForVariant(ctx, filter)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, 1, len(result))
|
|
}
|
|
|
|
func TestPlaybackABTestService_GetAnalyticsForVariant_WithDateFilter(t *testing.T) {
|
|
db, service := setupTestPlaybackABTestServiceDB(t)
|
|
ctx := context.Background()
|
|
|
|
// Créer user et track
|
|
userID := uuid.New()
|
|
trackID := uuid.New()
|
|
user := &models.User{ID: userID, Username: "testuser", Slug: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
track := &models.Track{
|
|
ID: trackID,
|
|
UserID: userID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
yesterday := now.AddDate(0, 0, -1)
|
|
tomorrow := now.AddDate(0, 0, 1)
|
|
|
|
// Analytics créé aujourd'hui
|
|
analytics := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: userID,
|
|
PlayTime: 180,
|
|
PauseCount: 0,
|
|
SeekCount: 0,
|
|
CompletionRate: 100.0,
|
|
StartedAt: now,
|
|
CreatedAt: now,
|
|
}
|
|
db.Create(analytics)
|
|
|
|
// Filtrer par date (hier à demain) - devrait inclure l'analytics
|
|
filter := VariantFilter{
|
|
TrackID: &trackID,
|
|
StartDate: &yesterday,
|
|
EndDate: &tomorrow,
|
|
}
|
|
result, err := service.getAnalyticsForVariant(ctx, filter)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 1, len(result))
|
|
|
|
// Filtrer par date (avant-hier à hier) - ne devrait pas inclure l'analytics
|
|
dayBeforeYesterday := now.AddDate(0, 0, -2)
|
|
filter2 := VariantFilter{
|
|
TrackID: &trackID,
|
|
StartDate: &dayBeforeYesterday,
|
|
EndDate: &yesterday,
|
|
}
|
|
result2, err := service.getAnalyticsForVariant(ctx, filter2)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 0, len(result2))
|
|
}
|
|
|
|
func TestPlaybackABTestService_GetAnalyticsForVariant_WithUserFilter(t *testing.T) {
|
|
db, service := setupTestPlaybackABTestServiceDB(t)
|
|
ctx := context.Background()
|
|
|
|
// Créer users et track
|
|
user1ID := uuid.New()
|
|
user2ID := uuid.New()
|
|
trackID := uuid.New()
|
|
user1 := &models.User{ID: user1ID, Username: "user1", Slug: "user1", Email: "user1@example.com", IsActive: true}
|
|
user2 := &models.User{ID: user2ID, Username: "user2", Slug: "user2", Email: "user2@example.com", IsActive: true}
|
|
db.Create(user1)
|
|
db.Create(user2)
|
|
track := &models.Track{
|
|
ID: trackID,
|
|
UserID: user1ID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
analytics1 := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: user1ID,
|
|
PlayTime: 180,
|
|
CompletionRate: 100.0,
|
|
StartedAt: now,
|
|
CreatedAt: now,
|
|
}
|
|
analytics2 := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: user2ID,
|
|
PlayTime: 90,
|
|
CompletionRate: 50.0,
|
|
StartedAt: now,
|
|
CreatedAt: now,
|
|
}
|
|
db.Create(analytics1)
|
|
db.Create(analytics2)
|
|
|
|
// Filtrer par user 1 seulement
|
|
filter := VariantFilter{
|
|
TrackID: &trackID,
|
|
UserIDs: []uuid.UUID{user1ID},
|
|
}
|
|
result, err := service.getAnalyticsForVariant(ctx, filter)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 1, len(result))
|
|
assert.Equal(t, user1ID, result[0].UserID)
|
|
}
|
|
|
|
func TestPlaybackABTestService_SafePercentageChange(t *testing.T) {
|
|
_, service := setupTestPlaybackABTestServiceDB(t)
|
|
|
|
// Test normal
|
|
result := service.safePercentageChange(100.0, 120.0)
|
|
assert.Equal(t, 20.0, result)
|
|
|
|
// Test avec base zéro et courant non-zéro
|
|
result2 := service.safePercentageChange(0.0, 100.0)
|
|
assert.True(t, math.IsInf(result2, 1))
|
|
|
|
// Test avec base zéro et courant zéro
|
|
result3 := service.safePercentageChange(0.0, 0.0)
|
|
assert.Equal(t, 0.0, result3)
|
|
|
|
// Test négatif
|
|
result4 := service.safePercentageChange(100.0, 80.0)
|
|
assert.Equal(t, -20.0, result4)
|
|
}
|
|
|
|
func TestPlaybackABTestService_CompareVariants_WithDateRange(t *testing.T) {
|
|
db, service := setupTestPlaybackABTestServiceDB(t)
|
|
ctx := context.Background()
|
|
|
|
// Créer user et track
|
|
userID := uuid.New()
|
|
trackID := uuid.New()
|
|
user := &models.User{ID: userID, Username: "testuser", Slug: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
track := &models.Track{
|
|
ID: trackID,
|
|
UserID: userID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
weekAgo := now.AddDate(0, 0, -7)
|
|
threeDaysAgo := now.AddDate(0, 0, -3)
|
|
|
|
// Analytics pour variant A (il y a une semaine)
|
|
analyticsA := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: userID,
|
|
PlayTime: 180,
|
|
CompletionRate: 100.0,
|
|
StartedAt: weekAgo,
|
|
CreatedAt: weekAgo,
|
|
}
|
|
db.Create(analyticsA)
|
|
|
|
// Analytics pour variant B (il y a 3 jours)
|
|
analyticsB := &models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: userID,
|
|
PlayTime: 90,
|
|
CompletionRate: 50.0,
|
|
StartedAt: threeDaysAgo,
|
|
CreatedAt: threeDaysAgo,
|
|
}
|
|
db.Create(analyticsB)
|
|
|
|
// Filtrer variant A par période (il y a 8 jours à 6 jours)
|
|
eightDaysAgo := now.AddDate(0, 0, -8)
|
|
sixDaysAgo := now.AddDate(0, 0, -6)
|
|
filterA := VariantFilter{
|
|
TrackID: &trackID,
|
|
StartDate: &eightDaysAgo,
|
|
EndDate: &sixDaysAgo,
|
|
}
|
|
|
|
// Filtrer variant B par période (il y a 4 jours à 2 jours)
|
|
fourDaysAgo := now.AddDate(0, 0, -4)
|
|
twoDaysAgo := now.AddDate(0, 0, -2)
|
|
filterB := VariantFilter{
|
|
TrackID: &trackID,
|
|
StartDate: &fourDaysAgo,
|
|
EndDate: &twoDaysAgo,
|
|
}
|
|
|
|
result, err := service.CompareVariants(ctx, "A", "B", filterA, filterB)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, int64(1), result.VariantA.TotalSessions)
|
|
assert.Equal(t, int64(1), result.VariantB.TotalSessions)
|
|
}
|