Skip to content

Commit 5f577f9

Browse files
authored
Merge pull request #1 from GoEddie/development
discover test classes created using tSQLt.NewTestClass rather than just the extended property
2 parents 8c149d8 + 8947770 commit 5f577f9

File tree

7 files changed

+87
-68
lines changed

7 files changed

+87
-68
lines changed

AgileSQLClub.tSQLtTestController/TestClass.cs

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
5-
using System.Text;
6-
using System.Threading.Tasks;
7-
using System.Windows.Forms;
85
using Microsoft.SqlServer.TransactSql.ScriptDom;
96

107
namespace AgileSQLClub.tSQLtTestController
@@ -20,10 +17,9 @@ public FileScanner(TSqlParser parser)
2017

2118
public ScanResults ScanCode(string code, ScanResults results, string path)
2219
{
23-
2420
var batches = code.Split(new[] {"\r\nGO\r\n", "\nGO\n"}, StringSplitOptions.None);
2521
var offset = 0;
26-
int lineOffset = 0;
22+
var lineOffset = 0;
2723

2824
foreach (var batch in batches)
2925
{
@@ -37,13 +33,12 @@ public ScanResults ScanCode(string code, ScanResults results, string path)
3733

3834
private ScanResults AppendResults(ScanResults results, string batch, string path, int offset, int lineOffset)
3935
{
40-
4136
var reader = new StringReader(batch);
4237
IList<ParseError> errors;
4338
var fragment = _parser.Parse(reader, out errors);
4439
var visitor = new TestVisitor(path, offset, lineOffset);
4540
fragment.Accept(visitor);
46-
41+
4742
results.FoundProperties.AddRange(visitor.ExtendedProperties);
4843
results.FoundClasses.AddRange(visitor.Schemas);
4944
results.FoundPotentialTests.AddRange(visitor.Procedures);
@@ -54,16 +49,16 @@ private ScanResults AppendResults(ScanResults results, string batch, string path
5449

5550
public class TestVisitor : TSqlFragmentVisitor
5651
{
52+
private readonly int _lineOffset;
53+
private readonly int _offset;
54+
private readonly string _path;
5755
public readonly List<tSQLtExtendedProperty> ExtendedProperties = new List<tSQLtExtendedProperty>();
56+
public readonly List<SqlProcedure> Procedures = new List<SqlProcedure>();
5857
public readonly List<SqlSchema> Schemas = new List<SqlSchema>();
59-
public readonly List<SqlProcedure> Procedures = new List<SqlProcedure>();
60-
private readonly string _path;
61-
private readonly int _offset;
62-
private readonly int _lineOffset;
6358

6459
public TestVisitor(string path, int offset, int lineOffset)
6560
{
66-
this._path = path;
61+
_path = path;
6762
_offset = offset;
6863
_lineOffset = lineOffset;
6964
}
@@ -75,9 +70,9 @@ public override void Visit(CreateProcedureStatement proc)
7570
name.Schema = son.SchemaIdentifier?.Value.UnQuote();
7671
name.Object = son.BaseIdentifier?.Value.UnQuote();
7772

78-
if(name.Object.ToLowerInvariant().StartsWith("test"))
79-
Procedures.Add(new SqlProcedure(name, _path, _offset+proc.StartOffset, proc.FragmentLength, _lineOffset + proc.StartLine));
80-
73+
if (name.Object.ToLowerInvariant().StartsWith("test"))
74+
Procedures.Add(new SqlProcedure(name, _path, _offset + proc.StartOffset, proc.FragmentLength, _lineOffset + proc.StartLine));
75+
8176
base.Visit(proc);
8277
}
8378

@@ -95,14 +90,11 @@ public override void Visit(ExecuteStatement exec)
9590

9691
if (!(exec.ExecuteSpecification.ExecutableEntity is ExecutableProcedureReference))
9792
return;
98-
93+
9994
var refereced = (ExecutableProcedureReference) exec.ExecuteSpecification.ExecutableEntity;
10095

101-
if (refereced.ProcedureReference.ProcedureReference != null && refereced.ProcedureReference.ProcedureReference.Name != null &&
102-
refereced.ProcedureReference.ProcedureReference.Name.BaseIdentifier.Value.IndexOf(
103-
"sp_addextendedproperty", StringComparison.OrdinalIgnoreCase) > -1)
96+
if (refereced.ProcedureReference.ProcedureReference != null && refereced.ProcedureReference.ProcedureReference.Name != null && refereced.ProcedureReference.ProcedureReference.Name.BaseIdentifier.Value.IndexOf("sp_addextendedproperty", StringComparison.OrdinalIgnoreCase) > -1)
10497
{
105-
10698
var propertyValue =
10799
refereced.Parameters.FirstOrDefault(
108100
p =>
@@ -112,13 +104,27 @@ public override void Visit(ExecuteStatement exec)
112104
if (propertyValue == null)
113105
return;
114106

115-
var schemaName =((refereced.Parameters.FirstOrDefault(p => p.Variable.Name.ToLowerInvariant() == "@level0name"))?.ParameterValue as StringLiteral)?.Value;
116-
if(!String.IsNullOrEmpty(schemaName))
117-
ExtendedProperties.Add(new tSQLtExtendedProperty(schemaName.UnQuote()));
107+
var schemaName = (refereced.Parameters.FirstOrDefault(p => p.Variable?.Name.ToLowerInvariant() == "@level0name")?.ParameterValue as StringLiteral)?.Value;
108+
if (!string.IsNullOrEmpty(schemaName))
109+
ExtendedProperties.Add(new tSQLtExtendedProperty(schemaName.UnQuote()));
118110
}
119-
120-
}
121111

112+
var name = refereced.ProcedureReference.ProcedureReference?.Name;
113+
if (name == null)
114+
return;
115+
116+
if (name.SchemaIdentifier?.Value.ToLowerInvariant() == "tsqlt" && name.BaseIdentifier?.Value.ToLowerInvariant() == "newtestclass")
117+
{
118+
var parameterValue = (refereced.Parameters.FirstOrDefault()?.ParameterValue as StringLiteral)?.Value;
119+
120+
if (!string.IsNullOrEmpty(parameterValue))
121+
{
122+
ExtendedProperties.Add(new tSQLtExtendedProperty(parameterValue.UnQuote()));
123+
Schemas.Add(new SqlSchema( parameterValue.UnQuote(),_path));
124+
}
125+
}
126+
127+
}
122128
}
123129

124130

@@ -131,12 +137,14 @@ public class ScanResults
131137

132138
public class SqlObjectName
133139
{
134-
public string Schema;
135140
public string Object;
141+
public string Schema;
136142
}
137143

138144
public class SqlProcedure
139145
{
146+
public SqlObjectName Name;
147+
140148
public SqlProcedure(SqlObjectName name, string path, int startPos, int endPos, int startLine)
141149
{
142150
Name = name;
@@ -150,40 +158,37 @@ public SqlProcedure(SqlObjectName name, string path, int startPos, int endPos, i
150158
public int StartPos { get; set; }
151159
public int EndPos { get; set; }
152160
public int StartLine { get; set; }
153-
154-
public SqlObjectName Name;
155-
156161
}
157162

158163
public class SqlSchema
159164
{
165+
public string Name;
166+
167+
public string Path;
168+
160169
public SqlSchema(string schemaName, string path)
161170
{
162171
Name = schemaName;
163172
Path = path;
164173
}
165-
166-
public string Path;
167-
public string Name;
168-
169174
}
170175

171176
public class tSQLtExtendedProperty
172177
{
178+
public string SchemaName;
179+
173180
public tSQLtExtendedProperty(string schemaName)
174181
{
175182
SchemaName = schemaName;
176183
}
177-
178-
public string SchemaName;
179184
}
180185

181186

182187
public class TestFinder
183188
{
184-
private readonly TSqlParser _parser;
185189
private readonly List<string> _filePaths;
186190
private readonly string _lookupPath;
191+
private readonly TSqlParser _parser;
187192

188193
public TestFinder(TSqlParser parser, List<string> filePaths)
189194
{
@@ -198,25 +203,24 @@ public List<TestClass> GetTests()
198203

199204
foreach (var path in _filePaths)
200205
{
201-
var scanner= new FileScanner(_parser);
206+
var scanner = new FileScanner(_parser);
202207
results = scanner.ScanCode(File.ReadAllText(path), results, path);
203208
}
204209

205210
var foundClasses =
206211
results.FoundClasses.Where(
207212
p =>
208213
results.FoundPotentialTests.Any(
209-
e => String.Equals(p.Name, e.Name.Schema, StringComparison.OrdinalIgnoreCase)));
214+
e => string.Equals(p.Name, e.Name.Schema, StringComparison.OrdinalIgnoreCase)));
210215

211216
var foundTests =
212217
results.FoundPotentialTests.Where(
213218
p =>
214219
results.FoundPotentialTests.Any(
215-
s => String.Equals(s.Name.Schema, p.Name.Schema, StringComparison.OrdinalIgnoreCase)));
220+
s => string.Equals(s.Name.Schema, p.Name.Schema, StringComparison.OrdinalIgnoreCase)));
216221

217222
return classes;
218223
}
219-
220224
}
221225

222226
public class TestClasses
@@ -236,4 +240,4 @@ public class Test
236240
public string Path;
237241
public int Line { get; set; }
238242
}
239-
}
243+
}

Test/UnitTests/tSQLtTestFinderTests.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace UnitTests
1313
[TestFixture]
1414
public class tSQLtTestFinderTests
1515
{
16-
private readonly TSqlParser _parser;
16+
private readonly TSqlParser _parser = new TSql140Parser(true);
1717

1818

1919
[Test]
@@ -59,5 +59,16 @@ public void Finds_Extended_Event_Procedure_In_Brackets()
5959

6060
}
6161

62+
[Test]
63+
public void Finds_Classes_Registered_With_NewTestClass()
64+
{
65+
var script = @"tSQLt.NewTestClass @ClassName = 'class name'";
66+
67+
var scanner = new FileScanner(_parser);
68+
var results = scanner.ScanCode(script, new ScanResults(), "path");
69+
Assert.True(results.FoundClasses.Any(p=>p.Name == "class name"));
70+
Assert.True(results.FoundProperties.Any(p => p.SchemaName == "class name"));
71+
}
72+
6273
}
6374
}

XMLTestAdapterVSIX/packages.config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<packages>
3+
<package id="Microsoft.VSSDK.Vsixsigntool" version="15.0.25604-Preview4" targetFramework="net45" />
4+
</packages>

XMLTestAdapterVSIX/source.extension.vsixmanifest

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
33
<Metadata>
4-
<Identity Id="AgileSQLClub.tSQLtTestAdapter" Version="0.59" Language="en-US" Publisher="EdElliott" />
4+
<Identity Id="AgileSQLClub.tSQLtTestAdapter" Version="0.63" Language="en-US" Publisher="EdElliott" />
55
<DisplayName>tSQLt Test Adapter</DisplayName>
66
<Description xml:space="preserve">Unit Test Adapter for tSQLt Tests</Description>
77
<MoreInfo>https://the.agilsql.club/projects/tSQLt-Test-Adapter</MoreInfo>
88
<License>LICENSE</License>
99
<Tags>tSQLt, Test, Adapter</Tags>
1010
</Metadata>
1111
<Installation>
12-
<InstallationTarget Id="Microsoft.VisualStudio.Pro" Version="[11.0,15.0)" />
13-
<InstallationTarget Version="[11.0,15.0)" Id="Microsoft.VisualStudio.Ultimate" />
14-
<InstallationTarget Version="[11.0,15.0)" Id="Microsoft.VisualStudio.Premium" />
12+
<InstallationTarget Id="Microsoft.VisualStudio.Pro" Version="[14.0,15.0)" />
13+
<InstallationTarget Version="[14.0,15.0)" Id="Microsoft.VisualStudio.Ultimate" />
14+
<InstallationTarget Version="[14.0,15.0)" Id="Microsoft.VisualStudio.Premium" />
1515
</Installation>
1616
<Dependencies>
1717
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="4.5" />

XMLTestAdapterVSIX/tSQLtTestAdapterVSIX.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
6262
<IncludeInVSIX>true</IncludeInVSIX>
6363
</Content>
64+
<None Include="packages.config" />
6465
<None Include="source.extension.vsixmanifest">
6566
<SubType>Designer</SubType>
6667
</None>

XmlTestAdapter/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@
3232
// You can specify all the values or you can default the Build and Revision Numbers
3333
// by using the '*' as shown below:
3434
// [assembly: AssemblyVersion("1.0.*")]
35-
[assembly: AssemblyVersion("0.0.0.1")]
36-
[assembly: AssemblyFileVersion("0.0.0.1")]
35+
[assembly: AssemblyVersion("0.0.0.2")]
36+
[assembly: AssemblyFileVersion("0.0.0.2")]

XmlTestAdapter/tSQLtTestDiscoverer.cs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Diagnostics;
43
using System.Linq;
54
using System.Text.RegularExpressions;
6-
using System.Windows.Forms;
7-
using AgileSQLClub.tSQLtTestController;
85
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
96
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
107
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
@@ -19,17 +16,17 @@ public class XmlTestDiscoverer : ITestDiscoverer
1916
private static readonly object _lock = new object();
2017
private static readonly TestCache _tests = new TestCache();
2118

19+
private static readonly List<Regex> _includePaths = new List<Regex>();
20+
2221
public void DiscoverTests(IEnumerable<string> sources, IDiscoveryContext discoveryContext, IMessageLogger logger, ITestCaseDiscoverySink discoverySink)
2322
{
24-
if (String.IsNullOrEmpty(
25-
new RunSettings(discoveryContext.RunSettings).GetSetting("TestDatabaseConnectionString")))
23+
if (string.IsNullOrEmpty(new RunSettings(discoveryContext.RunSettings).GetSetting("TestDatabaseConnectionString")))
2624
{
25+
logger.SendMessage(TestMessageLevel.Informational, "No RunSettings TestDatabaseConnectionString set - will not attempt to discover tests..");
2726
return;
2827
}
29-
30-
28+
3129
logger.SendMessage(TestMessageLevel.Informational, "tSQLt Test Adapter, searching for tests...");
32-
3330

3431
var includePath = new RunSettings(discoveryContext.RunSettings).GetSetting("IncludePath");
3532
SetPathFilter(includePath);
@@ -39,19 +36,17 @@ public void DiscoverTests(IEnumerable<string> sources, IDiscoveryContext discove
3936
GetTests(sources, discoverySink);
4037
}
4138

42-
if(_tests!= null)
43-
logger.SendMessage(TestMessageLevel.Informational, string.Format("tSQLt Test Adapter, searching for tests...done - {0} found", _tests.GetTests().Sum(p=>p.Tests.Count)));
39+
if (_tests != null)
40+
logger.SendMessage(TestMessageLevel.Informational, string.Format("tSQLt Test Adapter, searching for tests...done - {0} found", _tests.GetTests().Sum(p => p.Tests.Count)));
4441
else
4542
logger.SendMessage(TestMessageLevel.Informational, "tSQLt Test Adapter, searching for tests...done - none found");
4643
}
4744

48-
private static List<Regex> _includePaths = new List<Regex>();
49-
5045
public static void SetPathFilter(string includePath)
5146
{
5247
_includePaths.Clear();
5348

54-
if (!String.IsNullOrEmpty(includePath))
49+
if (!string.IsNullOrEmpty(includePath))
5550
{
5651
if (includePath.IndexOf(";", StringComparison.Ordinal) >= 0)
5752
{
@@ -72,9 +67,10 @@ public static List<TestCase> GetTests(IEnumerable<string> sources, ITestCaseDisc
7267
lock (_lock)
7368
{
7469
var tests = new List<TestCase>();
70+
7571
foreach (var source in sources)
7672
{
77-
if(_includePaths.Count == 0 || _includePaths.Any(p=>p.IsMatch(source)))
73+
if (_includePaths.Count == 0 || _includePaths.Any(p => p.IsMatch(source)))
7874
_tests.AddPath(source);
7975
}
8076

@@ -84,12 +80,14 @@ public static List<TestCase> GetTests(IEnumerable<string> sources, ITestCaseDisc
8480
{
8581
foreach (var test in testClass.Tests)
8682
{
87-
var testCase = new TestCase(string.Format("{0}.{1}", testClass.Name, test.Name), tSQLtTestExecutor.ExecutorUri, test.Path );
83+
var testCase = new TestCase(string.Format("{0}.{1}", testClass.Name, test.Name), tSQLtTestExecutor.ExecutorUri, test.Path);
84+
85+
8886
testCase.LineNumber = test.Line;
8987
testCase.CodeFilePath = test.Path;
90-
88+
9189
tests.Add(testCase);
92-
90+
9391
if (discoverySink != null)
9492
{
9593
discoverySink.SendTestCase(testCase);
@@ -99,14 +97,15 @@ public static List<TestCase> GetTests(IEnumerable<string> sources, ITestCaseDisc
9997
if (discoverySink != null)
10098
{
10199
var tcClass = new TestCase(testClass.Name + " TestClass", tSQLtTestExecutor.ExecutorUri, testClass.Path);
100+
102101
tcClass.CodeFilePath = testClass.Path;
103-
102+
104103
tests.Add(tcClass);
105-
104+
106105
discoverySink.SendTestCase(tcClass);
107106
}
108107
}
109-
108+
110109
return tests;
111110
}
112111
}

0 commit comments

Comments
 (0)