Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Commit 96c5063

Browse files
committed
More uncommented tests
1 parent ab73385 commit 96c5063

10 files changed

Lines changed: 682 additions & 527 deletions

src/Analysis/Engine/Test/AnalysisTest.cs

Lines changed: 556 additions & 485 deletions
Large diffs are not rendered by default.

src/Analysis/Engine/Test/FluentAssertions/AnalysisValueAssertions.cs

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,8 @@ public AndConstraint<TAssertions> HaveMemberOfTypes(string memberName, params Bu
128128
public AndConstraint<TAssertions> HaveMemberOfTypes(string memberName, IEnumerable<BuiltinTypeId> typeIds, string because = "", params object[] reasonArgs) {
129129
NotBeNull(because, reasonArgs);
130130

131-
Execute.Assertion.ForCondition(GetMember(memberName, out var member, out var errorMessage))
132-
.BecauseOf(because, reasonArgs)
133-
.FailWith(errorMessage);
131+
Execute.Assertion.BecauseOf(because, reasonArgs)
132+
.AssertHasMember(Subject, OwnerScope, GetName(), $"member '{memberName}'", out var member);
134133

135134
AssertTypeIds(member, typeIds, memberName, Is3X(OwnerScope), because, reasonArgs);
136135
return new AndConstraint<TAssertions>((TAssertions)this);
@@ -212,46 +211,12 @@ public AndWhichConstraint<TAssertions, AnalysisValueTestInfo<TMember>> HaveMembe
212211
where TMember : class, IAnalysisValue {
213212
NotBeNull(because, reasonArgs);
214213

215-
Execute.Assertion.ForCondition(GetMember(name, out TMember typedMember, out var errorMessage))
216-
.BecauseOf(because, reasonArgs)
217-
.FailWith(errorMessage);
214+
Execute.Assertion.BecauseOf(because, reasonArgs)
215+
.AssertHasMemberOfType(Subject, OwnerScope, GetName(), $"member '{name}'", out TMember typedMember);
218216

219217
return new AndWhichConstraint<TAssertions, AnalysisValueTestInfo<TMember>>((TAssertions)this, new AnalysisValueTestInfo<TMember>(typedMember, null, OwnerScope));
220218
}
221219

222-
private bool GetMember<TMember>(string name, out TMember typedMember, out string errorMessage) where TMember : class, IAnalysisValue {
223-
try {
224-
var member = Subject.GetMember(null, new AnalysisUnit(null, null, OwnerScope, true), name);
225-
typedMember = member as TMember;
226-
227-
errorMessage = member != null
228-
? typedMember != null
229-
? null
230-
: $"Expected {GetName()} to have a member '{name}' of type {typeof(TMember)}{{reason}}, but its type is {member.GetType()}."
231-
: $"Expected {GetName()} to have a member {name} of type {typeof(TMember)}{{reason}}.";
232-
return typedMember != null;
233-
} catch (Exception e) {
234-
errorMessage = $"Expected {GetName()} to have a member {name} of type {typeof(TMember)}{{reason}}, but {nameof(GetMember)} has failed with exception: {e}.";
235-
typedMember = null;
236-
return false;
237-
}
238-
}
239-
240-
private bool GetMember(string name, out IAnalysisSet member, out string errorMessage) {
241-
try {
242-
member = Subject.GetMember(null, new AnalysisUnit(null, null, OwnerScope, true), name);
243-
244-
errorMessage = member != null
245-
? null
246-
: $"Expected {GetName()} to have a member {name}{{reason}}.";
247-
return member != null;
248-
} catch (Exception e) {
249-
errorMessage = $"Expected {GetName()} to have a member {name}{{reason}}, but {nameof(GetMember)} has failed with exception: {e}.";
250-
member = null;
251-
return false;
252-
}
253-
}
254-
255220
protected virtual string GetName() => $"{GetQuotedName(Subject)} {ScopeDescription}";
256221

257222
private string GetOverloadName(string overload) => $"'{overload}' overload {ScopeDescription}";

src/Analysis/Engine/Test/FluentAssertions/AnalysisValueAssertionsExtensions.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,24 @@
1717
using System.Diagnostics.CodeAnalysis;
1818
using FluentAssertions;
1919
using Microsoft.PythonTools.Analysis.Values;
20+
using Microsoft.PythonTools.Interpreter;
2021

2122
namespace Microsoft.PythonTools.Analysis.FluentAssertions {
2223
[ExcludeFromCodeCoverage]
2324
internal static class AnalysisValueAssertionsExtensions {
25+
public static AndWhichConstraint<TAssertion, AnalysisValueTestInfo<TAnalysisValue>> OfPythonMemberType<TAssertion, TAnalysisValue>(this AndWhichConstraint<TAssertion, AnalysisValueTestInfo<TAnalysisValue>> constraint, PythonMemberType memberType)
26+
where TAnalysisValue : IAnalysisValue {
27+
new AnalysisValueAssertions<TAnalysisValue>(constraint.Which).HaveMemberType(memberType);
28+
return constraint;
29+
}
30+
31+
public static AndWhichConstraint<TAssertion, AnalysisValueTestInfo<TAnalysisValue>> WithMemberOfType<TAssertion, TAnalysisValue>(this AndWhichConstraint<TAssertion, AnalysisValueTestInfo<TAnalysisValue>> constraint, string name, PythonMemberType memberType)
32+
where TAnalysisValue : IAnalysisValue {
33+
var member = new AnalysisValueAssertions<TAnalysisValue>(constraint.Which).HaveMember<IAnalysisValue>(name) .Which;
34+
new AnalysisValueAssertions<IAnalysisValue>(member).HaveMemberType(memberType);
35+
return constraint;
36+
}
37+
2438
public static AndWhichConstraint<TAssertion, AnalysisValueTestInfo<IClassInfo>>
2539
WithMethodResolutionOrder<TAssertion>(this AndWhichConstraint<TAssertion, AnalysisValueTestInfo<IClassInfo>> constraint, params string[] classNames) {
2640
constraint.Which.Should().HaveMethodResolutionOrder(classNames);

src/Analysis/Engine/Test/FluentAssertions/AssertionsUtilities.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using System.Collections.Generic;
1919
using System.Linq;
2020
using System.Text;
21+
using FluentAssertions;
2122
using FluentAssertions.Execution;
2223
using Microsoft.PythonTools.Analysis.Analyzer;
2324
using Microsoft.PythonTools.Analysis.Infrastructure;
@@ -207,5 +208,43 @@ public static IEnumerable<IAnalysisValue> FlattenAnalysisValues(IEnumerable<IAna
207208

208209
public static string DoubleEscape(string input)
209210
=> input.Replace("\r", "\\\u200Br").Replace("\n", "\\\u200Bn").Replace("\t", @"\t");
211+
212+
[CustomAssertion]
213+
public static Continuation AssertIsNotNull<T>(this AssertionScope assertionScope, T instance, string subjectName, string itemName, string accessorName)
214+
where T : class
215+
=> assertionScope.ForCondition(!(instance is null))
216+
.FailWith($"Expected {subjectName} to have {itemName}{{reason}}, but {accessorName} is null.");
217+
218+
[CustomAssertion]
219+
public static Continuation AssertAtIndex<T, TItem>(this AssertionScope assertionScope, IReadOnlyList<T> collection, int index, string subjectName, string itemName)
220+
where T : class => assertionScope.ForCondition(collection.Count > index)
221+
.FailWith($"Expected {subjectName} to have {itemName} of type {typeof(T).Name} at index {index}{{reason}}, but collection has only {collection.Count} items.", subjectName, itemName)
222+
.Then
223+
.ForCondition(collection[index] is TItem)
224+
.FailWith($"Expected {subjectName} to have {itemName} of type `{typeof(T).Name}` at index {index}{{reason}}, but its type is `{collection[index].GetType().Name}`.");
225+
226+
[CustomAssertion]
227+
public static Continuation AssertHasMember(this AssertionScope assertionScope, IAnalysisValue analysisValue, IScope scope, string analysisValueName, string memberName, out IAnalysisSet member) {
228+
try {
229+
member = analysisValue.GetMember(null, new AnalysisUnit(null, null, scope, true), memberName);
230+
} catch (Exception e) {
231+
member = null;
232+
return assertionScope.FailWith($"Expected {analysisValueName} to have a {memberName}{{reason}}, but {nameof(analysisValue.GetMember)} has failed with exception: {e}.");
233+
}
234+
235+
return assertionScope.ForCondition(!(member is null))
236+
.FailWith($"Expected {analysisValueName} to have a {memberName}{{reason}}.");
237+
}
238+
239+
[CustomAssertion]
240+
public static Continuation AssertHasMemberOfType<TMember>(this AssertionScope assertionScope, IAnalysisValue analysisValue, IScope scope, string analysisValueName, string memberName, out TMember typedMember)
241+
where TMember : class, IAnalysisValue {
242+
var continuation = assertionScope.AssertHasMember(analysisValue, scope, analysisValueName, memberName, out var member)
243+
.Then
244+
.ForCondition(member is TMember)
245+
.FailWith($"Expected {analysisValueName} to have a {memberName} of type {typeof(TMember)}{{reason}}, but its type is {member.GetType()}.");
246+
typedMember = member as TMember;
247+
return continuation;
248+
}
210249
}
211250
}

src/Analysis/Engine/Test/FluentAssertions/CompletionItemAssertions.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,16 @@ public AndConstraint<CompletionItemAssertions> HaveInsertText(string insertText,
3939

4040
return new AndConstraint<CompletionItemAssertions>(this);
4141
}
42+
43+
[CustomAssertion]
44+
public AndConstraint<CompletionItemAssertions> HaveDocumentation(string documentation, string because = "", params object[] reasonArgs) {
45+
Execute.Assertion.BecauseOf(because, reasonArgs)
46+
.AssertIsNotNull(Subject.documentation, $"'{Subject.label}' completion", "documentation", "\'CompletionItem.documentation\'")
47+
.Then
48+
.ForCondition(string.Equals(Subject.documentation.value, documentation, StringComparison.Ordinal))
49+
.FailWith($"Expected '{Subject.label}' completion to have documentation '{documentation}'{{reason}}, but it has '{Subject.documentation.value}'");
50+
51+
return new AndConstraint<CompletionItemAssertions>(this);
52+
}
4253
}
4354
}

src/Analysis/Engine/Test/FluentAssertions/HoverAssertions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics.CodeAnalysis;
34
using System.Linq;
45
using FluentAssertions;
@@ -26,7 +27,7 @@ public AndConstraint<HoverAssertions> HaveTypeNames(IEnumerable<string> typeName
2627
NotBeNull(because, reasonArgs);
2728

2829
var expected = typeNames.ToArray();
29-
var actual = Subject._typeNames;
30+
var actual = Subject._typeNames ?? Array.Empty<string>();
3031
var errorMessage = GetAssertCollectionContainsMessage(actual, expected, "hover", "type name", "type names");
3132

3233
Execute.Assertion.ForCondition(errorMessage == null)

src/Analysis/Engine/Test/FluentAssertions/ModuleAnalysisAssertions.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
// See the Apache Version 2.0 License for specific language governing
1515
// permissions and limitations under the License.
1616

17+
using System;
1718
using System.Collections.Generic;
1819
using System.Diagnostics.CodeAnalysis;
1920
using FluentAssertions;
21+
using FluentAssertions.Execution;
2022
using FluentAssertions.Primitives;
2123
using Microsoft.PythonTools.Analysis.Analyzer;
2224
using Microsoft.PythonTools.Analysis.Values;
@@ -33,7 +35,21 @@ public ModuleAnalysisAssertions(IModuleAnalysis moduleAnalysis) {
3335
}
3436

3537
protected override string Identifier => nameof(IModuleAnalysis);
36-
38+
39+
public AndWhichConstraint<ModuleAnalysisAssertions, AnalysisValueTestInfo<TMember>> HaveBuiltinMember<TMember>(string name, string because = "", params object[] reasonArgs)
40+
where TMember : class, IAnalysisValue {
41+
NotBeNull(because, reasonArgs);
42+
43+
Execute.Assertion.BecauseOf(because, reasonArgs)
44+
.AssertIsNotNull(Subject.ProjectState, $"module '{Subject.ModuleName}'", "python analyzer", "\'IModuleAnalysis.ProjectState\'")
45+
.Then
46+
.AssertIsNotNull(Subject.ProjectState.BuiltinModule, $"module '{Subject.ModuleName}'", "builtin module", "\'IModuleAnalysis.ProjectState.BuiltinModule\'")
47+
.Then
48+
.AssertHasMemberOfType<TMember>(Subject.ProjectState.BuiltinModule, Subject.Scope, $"module '{Subject.ModuleName}'", $"builtin member '{name}'", out var typedMember);
49+
50+
return new AndWhichConstraint<ModuleAnalysisAssertions, AnalysisValueTestInfo<TMember>>(this, new AnalysisValueTestInfo<TMember>(typedMember, null, Subject.Scope));
51+
}
52+
3753
public AndWhichConstraint<ModuleAnalysisAssertions, IPythonModule> HavePythonModuleVariable(string name, string because = "", params object[] reasonArgs) {
3854
NotBeNull(because, reasonArgs);
3955
var constraint = _scopeAssertions.HavePythonModuleVariable(name, because, reasonArgs);

src/Analysis/Engine/Test/FluentAssertions/ScopeAssertions.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
// See the Apache Version 2.0 License for specific language governing
1515
// permissions and limitations under the License.
1616

17+
using System;
1718
using System.Collections.Generic;
1819
using System.Diagnostics.CodeAnalysis;
20+
using System.Linq;
1921
using FluentAssertions;
2022
using FluentAssertions.Execution;
2123
using FluentAssertions.Primitives;
@@ -39,6 +41,24 @@ public ScopeAssertions(TScope scope) {
3941

4042
protected override string Identifier => nameof(IScope);
4143

44+
[CustomAssertion]
45+
public AndWhichConstraint<TScopeAssertions, TChildScope> OnlyHaveChildScope<TChildScope>(string because = "", params object[] reasonArgs)
46+
where TChildScope : IScope => HaveChildScopeAt<TChildScope>(0, because, reasonArgs);
47+
48+
[CustomAssertion]
49+
public AndWhichConstraint<TScopeAssertions, TChildScope> HaveChildScopeAt<TChildScope>(int index, string because = "", params object[] reasonArgs)
50+
where TChildScope : IScope {
51+
NotBeNull(because, reasonArgs);
52+
var childScopes = Subject.Children;
53+
var subjectName = $"scope '{Subject.Name}'";
54+
Execute.Assertion.BecauseOf(because, reasonArgs)
55+
.AssertIsNotNull(childScopes, subjectName, $"child scope of type '{typeof(TScope).Name}'", $"'{Subject.Name}.Children'")
56+
.Then
57+
.AssertAtIndex<IScope, TChildScope>(childScopes, index, subjectName, "child scope");
58+
59+
return new AndWhichConstraint<TScopeAssertions, TChildScope>((TScopeAssertions)this, (TChildScope)childScopes[index]);
60+
}
61+
4262
public AndWhichConstraint<TScopeAssertions, IPythonModule> HavePythonModuleVariable(string name, string because = "", params object[] reasonArgs) {
4363
var assertion = HaveVariable(name, because, reasonArgs)
4464
.Which.Should().HaveValue<BuiltinModule>()

src/Analysis/Engine/Test/FluentAssertions/VariableDefAssertions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// See the Apache Version 2.0 License for specific language governing
1515
// permissions and limitations under the License.
1616

17+
using System;
1718
using System.Collections.Generic;
1819
using System.Linq;
1920
using FluentAssertions;
@@ -170,6 +171,18 @@ public AndConstraint<VariableDefAssertions> HaveDescription(string description,
170171
return new AndConstraint<VariableDefAssertions>(this);
171172
}
172173

174+
public AndConstraint<VariableDefAssertions> HaveDocumentation(string documentation, string because = "", params object[] reasonArgs) {
175+
var values = FlattenAnalysisValues(Subject.Types).ToArray();
176+
var value = AssertSingle(because, reasonArgs, values);
177+
178+
var actualDocumentation = value.Documentation;
179+
Execute.Assertion.ForCondition(string.Equals(documentation, actualDocumentation, StringComparison.Ordinal))
180+
.BecauseOf(because, reasonArgs)
181+
.FailWith($"Expected documentation of '{_moduleName}.{_name}' to have documentation '{documentation}'{{reason}}, but found '{actualDocumentation}'.");
182+
183+
return new AndConstraint<VariableDefAssertions>(this);
184+
}
185+
173186
[CustomAssertion]
174187
public AndConstraint<VariableDefAssertions> HaveShortDescriptions(params string[] descriptions) => HaveShortDescriptions(descriptions, string.Empty);
175188

src/Analysis/Engine/Test/FluentAssertions/VariableDefAssertionsExtensions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ public static AndWhichConstraint<TAssertion, VariableDefTestInfo> WithDescriptio
100100
return andWhichConstraint;
101101
}
102102

103+
public static AndWhichConstraint<TAssertion, VariableDefTestInfo> WithDocumentation<TAssertion>(this AndWhichConstraint<TAssertion, VariableDefTestInfo> andWhichConstraint, string documentation, string because = "", params object[] reasonArgs) {
104+
andWhichConstraint.Which.Should().HaveDocumentation(documentation, because, reasonArgs);
105+
return andWhichConstraint;
106+
}
107+
103108
public static AndWhichConstraint<TAssertion, VariableDefTestInfo> WithShortDescriptions<TAssertion>(this AndWhichConstraint<TAssertion, VariableDefTestInfo> andWhichConstraint, params string[] descriptions) {
104109
andWhichConstraint.Which.Should().HaveShortDescriptions(descriptions);
105110
return andWhichConstraint;

0 commit comments

Comments
 (0)