Skip to content

Commit 3220892

Browse files
Merge pull request #25 from cmdscale/test/further_increase_test_coverage
test: add comprehensive scaffolding and BulkCopy tests
2 parents aba9fb9 + 1e01dd7 commit 3220892

14 files changed

+4013
-37
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
![CmdScale Project](https://github.com/cmdscale/.github/raw/main/profile/assets/CmdShield.svg)
22
[![Test Workflow](https://github.com/cmdscale/CmdScale.EntityFrameworkCore.TimescaleDB/actions/workflows/run-tests.yml/badge.svg)](https://github.com/cmdscale/CmdScale.EntityFrameworkCore.TimescaleDB/actions/workflows/run-tests.yml)
3+
[![codecov](https://codecov.io/gh/cmdscale/CmdScale.EntityFrameworkCore.TimescaleDB/graph/badge.svg?token=YP3YCJLQ41)](https://codecov.io/gh/cmdscale/CmdScale.EntityFrameworkCore.TimescaleDB)
34
[![GitHub release (latest by date)](https://img.shields.io/github/v/tag/cmdscale/CmdScale.EntityFrameworkCore.TimescaleDB)](https://github.com/cmdscale/CmdScale.EntityFrameworkCore.TimescaleDB/tags)
45
[![GitHub issues](https://img.shields.io/github/issues/cmdscale/CmdScale.EntityFrameworkCore.TimescaleDB)](https://github.com/cmdscale/CmdScale.EntityFrameworkCore.TimescaleDB/issues)
56
[![GitHub license](https://img.shields.io/github/license/cmdscale/CmdScale.EntityFrameworkCore.TimescaleDB)](https://github.com/cmdscale/CmdScale.EntityFrameworkCore.TimescaleDB/blob/main/LICENSE)
@@ -176,14 +177,14 @@ Generate an HTML coverage report using [ReportGenerator](https://github.com/dani
176177
# Install ReportGenerator (once)
177178
dotnet tool install -g dotnet-reportgenerator-globaltool
178179

179-
# Run tests with coverage collection (output to ./TestResults)
180-
dotnet test --collect:"XPlat Code Coverage" --results-directory ./TestResults
180+
# Run tests with coverage collection
181+
dotnet test tests/Eftdb.Tests --settings tests/Eftdb.Tests/coverlet.runsettings --collect:"XPlat Code Coverage"
181182

182183
# Generate HTML report from coverage files
183-
reportgenerator -reports:"TestResults/**/coverage.cobertura.xml" -targetdir:"TestResults/CoverageReport" -reporttypes:Html
184+
reportgenerator -reports:"tests/Eftdb.Tests/TestResults/**/coverage.cobertura.xml" -targetdir:"tests/Eftdb.Tests/TestResults/CoverageReport" -reporttypes:Html
184185
```
185186

186-
The HTML report will be generated at `TestResults/CoverageReport/index.html`.
187+
The HTML report will be generated at `tests/Eftdb.Tests/TestResults/CoverageReport/index.html`.
187188

188189
### Mutation Testing
189190

codecov.yml

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,8 @@ coverage:
99
target: auto
1010
threshold: 2%
1111

12-
component_management:
13-
individual_components:
14-
- component_id: eftdb
15-
name: CmdScale.EntityFrameworkCore.TimescaleDB
16-
paths:
17-
- src/CmdScale.EntityFrameworkCore.TimescaleDB/**
18-
- component_id: eftdb-design
19-
name: CmdScale.EntityFrameworkCore.TimescaleDB.Design
20-
paths:
21-
- src/CmdScale.EntityFrameworkCore.TimescaleDB.Design/**
22-
23-
flag_management:
24-
individual_flags:
25-
- name: eftdb
26-
paths:
27-
- src/CmdScale.EntityFrameworkCore.TimescaleDB/**
28-
carryforward: true
29-
statuses:
30-
- type: project
31-
target: 80%
32-
- name: eftdb-design
33-
paths:
34-
- src/CmdScale.EntityFrameworkCore.TimescaleDB.Design/**
35-
carryforward: true
36-
statuses:
37-
- type: project
38-
target: 80%
39-
4012
comment:
41-
layout: "header, diff, flags, components, files"
13+
layout: "header, diff, files"
4214
behavior: default
4315
require_changes: true
4416

src/Eftdb/Internals/WhereClauseEpressionVisitor.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace CmdScale.EntityFrameworkCore.TimescaleDB.Internals
88
{
99

10+
// TODO: This is not in use, yet and will need more work to be functional. Therefore, this class will be ignored by code coverage tools. Don't forget to remove the exclusion when you start using it.
1011
/// <summary>
1112
/// A simplified visitor to translate a WHERE clause LambdaExpression into a SQL string.
1213
/// This must be used by your IMigrationsModelDiffer, not the SQL generator.

tests/Eftdb.Tests/Differs/ContinuousAggregateDifferTests.cs

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,4 +1880,212 @@ public void Should_Handle_Both_Null_Models()
18801880
}
18811881

18821882
#endregion
1883+
1884+
#region Should_Drop_And_Recreate_When_AggregateFunctions_Count_Differs
1885+
1886+
private class MetricEntity22
1887+
{
1888+
public DateTime Timestamp { get; set; }
1889+
public double Value { get; set; }
1890+
}
1891+
1892+
private class MetricAggregate22
1893+
{
1894+
public DateTime TimeBucket { get; set; }
1895+
public double AvgValue { get; set; }
1896+
}
1897+
1898+
private class MetricAggregateMultiple22
1899+
{
1900+
public DateTime TimeBucket { get; set; }
1901+
public double AvgValue { get; set; }
1902+
public double MaxValue { get; set; }
1903+
}
1904+
1905+
private class SingleAggregateFunctionContext22 : DbContext
1906+
{
1907+
public DbSet<MetricEntity22> Metrics => Set<MetricEntity22>();
1908+
public DbSet<MetricAggregate22> HourlyMetrics => Set<MetricAggregate22>();
1909+
1910+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
1911+
=> optionsBuilder.UseNpgsql("Host=localhost;Database=test;Username=test;Password=test")
1912+
.UseTimescaleDb();
1913+
1914+
protected override void OnModelCreating(ModelBuilder modelBuilder)
1915+
{
1916+
modelBuilder.Entity<MetricEntity22>(entity =>
1917+
{
1918+
entity.ToTable("Metrics");
1919+
entity.HasNoKey();
1920+
entity.IsHypertable(x => x.Timestamp);
1921+
});
1922+
1923+
modelBuilder.Entity<MetricAggregate22>(entity =>
1924+
{
1925+
entity.HasNoKey();
1926+
entity.IsContinuousAggregate<MetricAggregate22, MetricEntity22>(
1927+
"hourly_metrics",
1928+
"1 hour",
1929+
x => x.Timestamp)
1930+
.AddAggregateFunction(x => x.AvgValue, x => x.Value, EAggregateFunction.Avg);
1931+
});
1932+
}
1933+
}
1934+
1935+
private class MultipleAggregateFunctionsContext22 : DbContext
1936+
{
1937+
public DbSet<MetricEntity22> Metrics => Set<MetricEntity22>();
1938+
public DbSet<MetricAggregateMultiple22> HourlyMetrics => Set<MetricAggregateMultiple22>();
1939+
1940+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
1941+
=> optionsBuilder.UseNpgsql("Host=localhost;Database=test;Username=test;Password=test")
1942+
.UseTimescaleDb();
1943+
1944+
protected override void OnModelCreating(ModelBuilder modelBuilder)
1945+
{
1946+
modelBuilder.Entity<MetricEntity22>(entity =>
1947+
{
1948+
entity.ToTable("Metrics");
1949+
entity.HasNoKey();
1950+
entity.IsHypertable(x => x.Timestamp);
1951+
});
1952+
1953+
modelBuilder.Entity<MetricAggregateMultiple22>(entity =>
1954+
{
1955+
entity.HasNoKey();
1956+
entity.IsContinuousAggregate<MetricAggregateMultiple22, MetricEntity22>(
1957+
"hourly_metrics",
1958+
"1 hour",
1959+
x => x.Timestamp)
1960+
.AddAggregateFunction(x => x.AvgValue, x => x.Value, EAggregateFunction.Avg)
1961+
.AddAggregateFunction(x => x.MaxValue, x => x.Value, EAggregateFunction.Max);
1962+
});
1963+
}
1964+
}
1965+
1966+
[Fact]
1967+
public void Should_Drop_And_Recreate_When_AggregateFunctions_Count_Differs()
1968+
{
1969+
using SingleAggregateFunctionContext22 sourceContext = new();
1970+
using MultipleAggregateFunctionsContext22 targetContext = new();
1971+
1972+
IRelationalModel sourceModel = GetModel(sourceContext);
1973+
IRelationalModel targetModel = GetModel(targetContext);
1974+
1975+
ContinuousAggregateDiffer differ = new();
1976+
1977+
IReadOnlyList<MigrationOperation> operations = differ.GetDifferences(sourceModel, targetModel);
1978+
1979+
Assert.Contains(operations, op => op is DropContinuousAggregateOperation);
1980+
Assert.Contains(operations, op => op is CreateContinuousAggregateOperation);
1981+
}
1982+
1983+
#endregion
1984+
1985+
#region Should_Drop_And_Recreate_When_GroupByColumns_Count_Differs
1986+
1987+
private class MetricEntity23
1988+
{
1989+
public DateTime Timestamp { get; set; }
1990+
public double Value { get; set; }
1991+
public string? Category { get; set; }
1992+
public string? Region { get; set; }
1993+
}
1994+
1995+
private class MetricAggregateSingleGroupBy23
1996+
{
1997+
public DateTime TimeBucket { get; set; }
1998+
public double AvgValue { get; set; }
1999+
public string? Category { get; set; }
2000+
}
2001+
2002+
private class MetricAggregateMultipleGroupBy23
2003+
{
2004+
public DateTime TimeBucket { get; set; }
2005+
public double AvgValue { get; set; }
2006+
public string? Category { get; set; }
2007+
public string? Region { get; set; }
2008+
}
2009+
2010+
private class SingleGroupByColumnContext23 : DbContext
2011+
{
2012+
public DbSet<MetricEntity23> Metrics => Set<MetricEntity23>();
2013+
public DbSet<MetricAggregateSingleGroupBy23> HourlyMetrics => Set<MetricAggregateSingleGroupBy23>();
2014+
2015+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
2016+
=> optionsBuilder.UseNpgsql("Host=localhost;Database=test;Username=test;Password=test")
2017+
.UseTimescaleDb();
2018+
2019+
protected override void OnModelCreating(ModelBuilder modelBuilder)
2020+
{
2021+
modelBuilder.Entity<MetricEntity23>(entity =>
2022+
{
2023+
entity.ToTable("Metrics");
2024+
entity.HasNoKey();
2025+
entity.IsHypertable(x => x.Timestamp);
2026+
});
2027+
2028+
modelBuilder.Entity<MetricAggregateSingleGroupBy23>(entity =>
2029+
{
2030+
entity.HasNoKey();
2031+
entity.IsContinuousAggregate<MetricAggregateSingleGroupBy23, MetricEntity23>(
2032+
"hourly_metrics",
2033+
"1 hour",
2034+
x => x.Timestamp)
2035+
.AddAggregateFunction(x => x.AvgValue, x => x.Value, EAggregateFunction.Avg)
2036+
.AddGroupByColumn(x => x.Category);
2037+
});
2038+
}
2039+
}
2040+
2041+
private class MultipleGroupByColumnsContext23 : DbContext
2042+
{
2043+
public DbSet<MetricEntity23> Metrics => Set<MetricEntity23>();
2044+
public DbSet<MetricAggregateMultipleGroupBy23> HourlyMetrics => Set<MetricAggregateMultipleGroupBy23>();
2045+
2046+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
2047+
=> optionsBuilder.UseNpgsql("Host=localhost;Database=test;Username=test;Password=test")
2048+
.UseTimescaleDb();
2049+
2050+
protected override void OnModelCreating(ModelBuilder modelBuilder)
2051+
{
2052+
modelBuilder.Entity<MetricEntity23>(entity =>
2053+
{
2054+
entity.ToTable("Metrics");
2055+
entity.HasNoKey();
2056+
entity.IsHypertable(x => x.Timestamp);
2057+
});
2058+
2059+
modelBuilder.Entity<MetricAggregateMultipleGroupBy23>(entity =>
2060+
{
2061+
entity.HasNoKey();
2062+
entity.IsContinuousAggregate<MetricAggregateMultipleGroupBy23, MetricEntity23>(
2063+
"hourly_metrics",
2064+
"1 hour",
2065+
x => x.Timestamp)
2066+
.AddAggregateFunction(x => x.AvgValue, x => x.Value, EAggregateFunction.Avg)
2067+
.AddGroupByColumn(x => x.Category)
2068+
.AddGroupByColumn(x => x.Region);
2069+
});
2070+
}
2071+
}
2072+
2073+
[Fact]
2074+
public void Should_Drop_And_Recreate_When_GroupByColumns_Count_Differs()
2075+
{
2076+
using SingleGroupByColumnContext23 sourceContext = new();
2077+
using MultipleGroupByColumnsContext23 targetContext = new();
2078+
2079+
IRelationalModel sourceModel = GetModel(sourceContext);
2080+
IRelationalModel targetModel = GetModel(targetContext);
2081+
2082+
ContinuousAggregateDiffer differ = new();
2083+
2084+
IReadOnlyList<MigrationOperation> operations = differ.GetDifferences(sourceModel, targetModel);
2085+
2086+
Assert.Contains(operations, op => op is DropContinuousAggregateOperation);
2087+
Assert.Contains(operations, op => op is CreateContinuousAggregateOperation);
2088+
}
2089+
2090+
#endregion
18832091
}

0 commit comments

Comments
 (0)