-
Notifications
You must be signed in to change notification settings - Fork 292
Expand file tree
/
Copy pathTestDataSource.cs
More file actions
148 lines (129 loc) · 6.63 KB
/
TestDataSource.cs
File metadata and controls
148 lines (129 loc) · 6.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#if NETFRAMEWORK
using System.Configuration;
using System.Data;
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Data;
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Extensions;
#endif
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ITestDataSource = Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.ITestDataSource;
namespace Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices;
/// <summary>
/// The platform service that provides values from data source when data driven tests are run.
/// </summary>
/// <remarks>
/// NOTE NOTE NOTE: This platform service refers to the inbox UTF extension assembly for UTF.TestContext which can only be loadable inside of the app domain that discovers/runs
/// the tests since it can only be found at the test output directory. DO NOT call into this platform service outside of the appdomain context if you do not want to hit
/// a ReflectionTypeLoadException.
/// </remarks>
internal sealed class TestDataSource : ITestDataSource
{
/// <summary>
/// Gets the test data from custom test data source and sets dbconnection in testContext object.
/// </summary>
/// <param name="testMethodInfo">The test method info.</param>
/// <param name="testContext">The test context.</param>
/// <returns>The test data.</returns>
#if NETFRAMEWORK
public IEnumerable<object>? GetData(ITestMethod testMethodInfo, ITestContext testContext)
#else
IEnumerable<object>? ITestDataSource.GetData(ITestMethod testMethodInfo, ITestContext testContext)
#endif
{
#if NETFRAMEWORK
// Figure out where (as well as the current directory) we could look for data files
// for unit tests this means looking at the location of the test itself
List<string> dataFolders =
[
Path.GetDirectoryName(new Uri(testMethodInfo.MethodInfo.Module.Assembly.CodeBase).LocalPath),
];
List<TestResult> dataRowResults = [];
// Connect to data source.
TestDataConnectionFactory factory = new();
GetConnectionProperties(testMethodInfo.GetAttributes<DataSourceAttribute>()[0], out string providerNameInvariant, out string? connectionString, out string? tableName, out DataAccessMethod dataAccessMethod);
try
{
using TestDataConnection connection = factory.Create(providerNameInvariant, connectionString!, dataFolders);
DataTable? table = connection.ReadTable(tableName!, null);
DebugEx.Assert(table != null, "Table should not be null");
DataRow[] rows = table!.Select();
DebugEx.Assert(rows != null, "rows should not be null.");
// check for row length is 0
if (rows.Length == 0)
{
return null;
}
IEnumerable<int> permutation = GetPermutation(dataAccessMethod, rows.Length);
object[] rowsAfterPermutation = new object[rows.Length];
int index = 0;
foreach (int rowIndex in permutation)
{
rowsAfterPermutation[index++] = rows[rowIndex];
}
testContext.SetDataConnection(connection.Connection);
return rowsAfterPermutation;
}
catch (Exception ex)
{
string message = ex.GetExceptionMessage();
// TODO: Change exception type to more specific one.
#pragma warning disable CA2201 // Do not raise reserved exception types
throw new Exception(string.Format(CultureInfo.CurrentCulture, Resource.UTA_ErrorDataConnectionFailed, message), ex);
#pragma warning restore CA2201 // Do not raise reserved exception types
}
#else
return null;
#endif
}
#if NETFRAMEWORK
/// <summary>
/// Get permutations for data row access.
/// </summary>
/// <param name="dataAccessMethod">The data access method.</param>
/// <param name="length">Number of permutations.</param>
/// <returns>Permutations.</returns>
private static IEnumerable<int> GetPermutation(DataAccessMethod dataAccessMethod, int length)
{
switch (dataAccessMethod)
{
case DataAccessMethod.Sequential:
return new SequentialIntPermutation(length);
case DataAccessMethod.Random:
return new RandomIntPermutation(length);
default:
Debug.Fail("Unknown DataAccessMethod: " + dataAccessMethod);
return new SequentialIntPermutation(length);
}
}
/// <summary>
/// Get connection property based on DataSourceAttribute. If its in config file then read it from config.
/// </summary>
/// <param name="dataSourceAttribute">The dataSourceAttribute.</param>
/// <param name="providerNameInvariant">The provider name.</param>
/// <param name="connectionString">The connection string.</param>
/// <param name="tableName">The table name.</param>
/// <param name="dataAccessMethod">The data access method.</param>
private static void GetConnectionProperties(DataSourceAttribute dataSourceAttribute, out string providerNameInvariant,
out string? connectionString, out string? tableName, out DataAccessMethod dataAccessMethod)
{
if (StringEx.IsNullOrEmpty(dataSourceAttribute.DataSourceSettingName))
{
providerNameInvariant = dataSourceAttribute.ProviderInvariantName;
connectionString = dataSourceAttribute.ConnectionString;
tableName = dataSourceAttribute.TableName;
dataAccessMethod = dataSourceAttribute.DataAccessMethod;
return;
}
DataSourceElement element = TestConfiguration.ConfigurationSection.DataSources[dataSourceAttribute.DataSourceSettingName]
#pragma warning disable CA2201 // Do not raise reserved exception types
?? throw new Exception(string.Format(CultureInfo.CurrentCulture, Resource.UTA_DataSourceConfigurationSectionMissing, dataSourceAttribute.DataSourceSettingName));
#pragma warning restore CA2201 // Do not raise reserved exception types
providerNameInvariant = ConfigurationManager.ConnectionStrings[element.ConnectionString].ProviderName;
connectionString = ConfigurationManager.ConnectionStrings[element.ConnectionString].ConnectionString;
tableName = element.DataTableName;
dataAccessMethod = (DataAccessMethod)Enum.Parse(typeof(DataAccessMethod), element.DataAccessMethod);
}
#endif
}