• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

fluentassertions / fluentassertions.datasets / 7436892764

07 Jan 2024 07:47AM UTC coverage: 94.435%. First build
7436892764

Pull #3

github

dennisdoomen
Update package references, refactor code, and fix namespace

Updated the package references in the csproj files. Refactored the code in several files to improve readability and maintainability. Also, fixed the namespace in the DataTableAssertionExtensions and DataRowAssertionExtensions classes to align with standard conventions. No functional changes were made.
Pull Request #3: Clean-up and finalization of data set support

440 of 480 branches covered (0.0%)

Branch coverage included in aggregate %.

1308 of 1371 relevant lines covered (95.4%)

2664.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.52
/Src/FluentAssertions.DataSets/DataEquivalencyAssertionOptions.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Data;
4
using System.Linq.Expressions;
5
using System.Reflection;
6
using FluentAssertions.Equivalency;
7

8
namespace FluentAssertions.DataSets;
9

10
internal class DataEquivalencyAssertionOptions<T> : EquivalencyAssertionOptions<T>, IDataEquivalencyAssertionOptions<T>
11
{
12
    private readonly HashSet<string> excludeTableNames = new();
556✔
13
    private readonly HashSet<string> excludeColumnNames = new();
556✔
14
    private readonly Dictionary<string, HashSet<string>> excludeColumnNamesByTableName = new();
556✔
15

16
    public bool AllowMismatchedTypes { get; private set; }
5,454✔
17

18
    public bool IgnoreUnmatchedColumns { get; private set; }
4,760✔
19

20
    public bool ExcludeOriginalData { get; private set; }
4,762✔
21

22
    public RowMatchMode RowMatchMode { get; private set; }
514✔
23

24
    public ISet<string> ExcludeTableNames => excludeTableNames;
296✔
25

26
    public ISet<string> ExcludeColumnNames => excludeColumnNames;
×
27

28
    public DataEquivalencyAssertionOptions(EquivalencyAssertionOptions<T> defaults)
29
        : base(defaults)
556✔
30
    {
31
    }
556✔
32

33
    public IDataEquivalencyAssertionOptions<T> AllowingMismatchedTypes()
34
    {
35
        AllowMismatchedTypes = true;
10✔
36
        return this;
10✔
37
    }
38

39
    public IDataEquivalencyAssertionOptions<T> IgnoringUnmatchedColumns()
40
    {
41
        IgnoreUnmatchedColumns = true;
×
42
        return this;
×
43
    }
44

45
    public IDataEquivalencyAssertionOptions<T> UsingRowMatchMode(RowMatchMode rowMatchMode)
46
    {
47
        RowMatchMode = rowMatchMode;
16✔
48
        return this;
16✔
49
    }
50

51
    public IDataEquivalencyAssertionOptions<T> ExcludingOriginalData()
52
    {
53
        ExcludeOriginalData = true;
2✔
54
        return this;
2✔
55
    }
56

57
    public new IDataEquivalencyAssertionOptions<T> Excluding(Expression<Func<T, object>> expression)
58
    {
59
        base.Excluding(expression);
250✔
60
        return this;
250✔
61
    }
62

63
    public IDataEquivalencyAssertionOptions<T> ExcludingRelated(Expression<Func<DataRelation, object>> expression)
64
    {
65
        ExcludeMemberOfRelatedTypeByGeneratedPredicate(expression);
28✔
66
        return this;
28✔
67
    }
68

69
    public IDataEquivalencyAssertionOptions<T> ExcludingRelated(Expression<Func<DataTable, object>> expression)
70
    {
71
        ExcludeMemberOfRelatedTypeByGeneratedPredicate(expression);
42✔
72
        return this;
42✔
73
    }
74

75
    public IDataEquivalencyAssertionOptions<T> ExcludingRelated(Expression<Func<DataColumn, object>> expression)
76
    {
77
        ExcludeMemberOfRelatedTypeByGeneratedPredicate(expression);
30✔
78
        return this;
30✔
79
    }
80

81
    public IDataEquivalencyAssertionOptions<T> ExcludingRelated(Expression<Func<DataRow, object>> expression)
82
    {
83
        ExcludeMemberOfRelatedTypeByGeneratedPredicate(expression);
4✔
84
        return this;
4✔
85
    }
86

87
    public IDataEquivalencyAssertionOptions<T> ExcludingRelated(Expression<Func<Constraint, object>> expression)
88
    {
89
        ExcludeMemberOfSubtypeOfRelatedTypeByGeneratedPredicate<Constraint, ForeignKeyConstraint, object>(expression);
6✔
90
        ExcludeMemberOfSubtypeOfRelatedTypeByGeneratedPredicate<Constraint, UniqueConstraint, object>(expression);
4✔
91
        return this;
4✔
92
    }
93

94
    public IDataEquivalencyAssertionOptions<T> ExcludingRelated(Expression<Func<ForeignKeyConstraint, object>> expression)
95
    {
96
        ExcludeMemberOfRelatedTypeByGeneratedPredicate(expression);
×
97
        return this;
×
98
    }
99

100
    public IDataEquivalencyAssertionOptions<T> ExcludingRelated(Expression<Func<UniqueConstraint, object>> expression)
101
    {
102
        ExcludeMemberOfRelatedTypeByGeneratedPredicate(expression);
×
103
        return this;
×
104
    }
105

106
    private void ExcludeMemberOfRelatedTypeByGeneratedPredicate<TDeclaringType, TPropertyType>(
107
        Expression<Func<TDeclaringType, TPropertyType>> expression)
108
    {
109
        Expression<Func<IMemberInfo, bool>> predicate = BuildMemberSelectionPredicate(
104✔
110
            typeof(TDeclaringType),
104✔
111
            GetMemberAccessTargetMember(expression.Body));
104✔
112

113
        Excluding(predicate);
104✔
114
    }
104✔
115

116
    private void ExcludeMemberOfSubtypeOfRelatedTypeByGeneratedPredicate<TDeclaringType, TInheritingType, TPropertyType>(
117
        Expression<Func<TDeclaringType, TPropertyType>> expression)
118
        where TInheritingType : TDeclaringType
119
    {
120
        Expression<Func<IMemberInfo, bool>> predicate = BuildMemberSelectionPredicate(
10✔
121
            typeof(TInheritingType),
10✔
122
            GetMemberAccessTargetMember(expression.Body));
10✔
123

124
        Excluding(predicate);
8✔
125
    }
8✔
126

127
    private static MemberInfo GetMemberAccessTargetMember(Expression expression)
128
    {
129
        if (expression is UnaryExpression { NodeType: ExpressionType.Convert } unaryExpression)
114✔
130
        {
131
            // If the expression is a value type, then accessing it will involve an
132
            // implicit boxing conversion to type object that we need to ignore.
133
            expression = unaryExpression.Operand;
28✔
134
        }
135

136
        if (expression is MemberExpression memberExpression)
114✔
137
        {
138
            return memberExpression.Member;
112✔
139
        }
140

141
        throw new ArgumentException("Expression must be a simple member access", nameof(expression));
2✔
142
    }
143

144
    private static Expression<Func<IMemberInfo, bool>> BuildMemberSelectionPredicate(Type relatedSubjectType,
145
        MemberInfo referencedMember)
146
    {
147
        ParameterExpression predicateMemberInfoArgument = Expression.Parameter(typeof(IMemberInfo));
112✔
148

149
        BinaryExpression typeComparison = Expression.Equal(
112✔
150
            Expression.MakeMemberAccess(
112✔
151
                predicateMemberInfoArgument,
112✔
152
                typeof(IMemberInfo).GetProperty(nameof(IMemberInfo.DeclaringType))),
112✔
153
            Expression.Constant(relatedSubjectType));
112✔
154

155
        BinaryExpression memberNameComparison = Expression.Equal(
112✔
156
            Expression.MakeMemberAccess(
112✔
157
                predicateMemberInfoArgument,
112✔
158
                typeof(IMemberInfo).GetProperty(nameof(IMemberInfo.Name))),
112✔
159
            Expression.Constant(referencedMember.Name));
112✔
160

161
        BinaryExpression predicateBody = Expression.AndAlso(
112✔
162
            typeComparison,
112✔
163
            memberNameComparison);
112✔
164

165
        return Expression.Lambda<Func<IMemberInfo, bool>>(
112✔
166
            predicateBody,
112✔
167
            predicateMemberInfoArgument);
112✔
168
    }
169

170
    public new IDataEquivalencyAssertionOptions<T> Excluding(Expression<Func<IMemberInfo, bool>> predicate)
171
    {
172
        base.Excluding(predicate);
120✔
173
        return this;
120✔
174
    }
175

176
    public IDataEquivalencyAssertionOptions<T> ExcludingTable(string tableName)
177
    {
178
        return ExcludingTables(tableName);
4✔
179
    }
180

181
    public IDataEquivalencyAssertionOptions<T> ExcludingTables(params string[] tableNames)
182
    {
183
        return ExcludingTables((IEnumerable<string>)tableNames);
10✔
184
    }
185

186
    public IDataEquivalencyAssertionOptions<T> ExcludingTables(IEnumerable<string> tableNames)
187
    {
188
        excludeTableNames.UnionWith(tableNames);
12✔
189
        return this;
12✔
190
    }
191

192
    public IDataEquivalencyAssertionOptions<T> ExcludingColumnInAllTables(string columnName)
193
    {
194
        return ExcludingColumnsInAllTables(columnName);
2✔
195
    }
196

197
    public IDataEquivalencyAssertionOptions<T> ExcludingColumnsInAllTables(params string[] columnNames)
198
    {
199
        return ExcludingColumnsInAllTables((IEnumerable<string>)columnNames);
2✔
200
    }
201

202
    public IDataEquivalencyAssertionOptions<T> ExcludingColumnsInAllTables(IEnumerable<string> columnNames)
203
    {
204
        excludeColumnNames.UnionWith(columnNames);
2✔
205
        return this;
2✔
206
    }
207

208
    public IDataEquivalencyAssertionOptions<T> ExcludingColumn(DataColumn column)
209
    {
210
        return ExcludingColumn(column.Table.TableName, column.ColumnName);
12✔
211
    }
212

213
    public IDataEquivalencyAssertionOptions<T> ExcludingColumns(params DataColumn[] columns)
214
    {
215
        return ExcludingColumns((IEnumerable<DataColumn>)columns);
2✔
216
    }
217

218
    public IDataEquivalencyAssertionOptions<T> ExcludingColumns(IEnumerable<DataColumn> columns)
219
    {
220
        foreach (DataColumn column in columns)
16✔
221
        {
222
            ExcludingColumn(column);
4✔
223
        }
224

225
        return this;
4✔
226
    }
227

228
    public IDataEquivalencyAssertionOptions<T> ExcludingColumn(string tableName, string columnName)
229
    {
230
        return ExcludingColumns(tableName, columnName);
12✔
231
    }
232

233
    public IDataEquivalencyAssertionOptions<T> ExcludingColumns(string tableName, params string[] columnNames)
234
    {
235
        return ExcludingColumns(tableName, (IEnumerable<string>)columnNames);
12✔
236
    }
237

238
    public IDataEquivalencyAssertionOptions<T> ExcludingColumns(string tableName, IEnumerable<string> columnNames)
239
    {
240
        if (!excludeColumnNamesByTableName.TryGetValue(tableName, out HashSet<string> excludeColumnNames))
12✔
241
        {
242
            excludeColumnNames = new HashSet<string>();
12✔
243
            excludeColumnNamesByTableName[tableName] = excludeColumnNames;
12✔
244
        }
245

246
        excludeColumnNames.UnionWith(columnNames);
12✔
247

248
        return this;
12✔
249
    }
250

251
    public bool ShouldExcludeColumn(DataColumn column)
252
    {
253
        if (excludeColumnNames.Contains(column.ColumnName))
32,832✔
254
        {
255
            return true;
2✔
256
        }
257

258
        return excludeColumnNamesByTableName.TryGetValue(column.Table.TableName, out HashSet<string> excludeColumnsForTable)
32,830✔
259
            && excludeColumnsForTable.Contains(column.ColumnName);
32,830✔
260
    }
261
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc