Skip to content

Commit

Permalink
ci: moved from MSTest to Xunit
Browse files Browse the repository at this point in the history
  • Loading branch information
Mastermindzh committed Oct 30, 2023
1 parent 8a24e63 commit 179b5fa
Show file tree
Hide file tree
Showing 16 changed files with 261 additions and 245 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ jobs:
run: dotnet build GrowthBook/GrowthBook.csproj --configuration Release

# current tests are written for visual studio only
# - name: Test
# run: dotnet test Test/Growthook.Tests.csproj --configuration Release --no-build
- name: Test
run: dotnet test GrowthBook.Tests/GrowthBook.Tests.csproj --logger:"console;verbosity=normal"

- name: pack
run: dotnet pack --configuration Release --no-build --output dist GrowthBook/GrowthBook.csproj
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.2]

- ci: moved from MSTest to Xunit

## [0.1.1]

- Handle null namespace property.
Expand Down
51 changes: 51 additions & 0 deletions GrowthBook.Tests/GrowthBook.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>

<ItemGroup>
<None Remove="Json/custom-cases.json" />
<None Remove="Json/FeatureDictionary.json" />
<None Remove="Json/GrowthBookContext.json" />
<None Remove="Json/GrowthBookContext.NoFeatures.json" />
<None Remove="Json/SingleFeatureDictionary.WithNameSpace.json" />
<None Remove="Json/standard-cases.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Json/custom-cases.json" />
<EmbeddedResource Include="Json/FeatureDictionary.json" />
<EmbeddedResource Include="Json/GrowthBookContext.json" />
<EmbeddedResource Include="Json/GrowthBookContext.NoFeatures.json" />
<EmbeddedResource Include="Json/SingleFeatureDictionary.WithNameSpace.json" />
<EmbeddedResource Include="Json/standard-cases.json" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.5.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.10" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="XunitXml.TestLogger" Version="3.0.70" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.0" />
</ItemGroup>

<ItemGroup>
<Folder Include="test-results/" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../GrowthBook/GrowthBook.csproj" />
</ItemGroup>

</Project>
140 changes: 70 additions & 70 deletions Test/GrowthBookTests.cs → GrowthBook.Tests/GrowthBookTests.cs
Original file line number Diff line number Diff line change
@@ -1,57 +1,40 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using GrowthBook;
using Growthbook.Tests.Json;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using GrowthBook.Tests.Json;

using Newtonsoft.Json.Linq;
using Test;

namespace Growthbook.Tests
using Xunit;

namespace GrowthBook.Tests
{
[TestClass]
public class GrowthBookTests
{
public static JObject testCases;
public static JObject customCases;

[ClassInitialize]
public static void TestFixtureSetup(TestContext context)
#region helpers
public static JObject getStandardCases()
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}

testCases = JObject.Parse(JsonTestHelpers.GetTestJson("standard-cases"));
customCases = JObject.Parse(JsonTestHelpers.GetTestJson("custom-cases"));
return JObject.Parse(JsonTestHelpers.GetTestJson("standard-cases"));
}

public static string GetTestNames(MethodInfo methodInfo, object[] values)
public static JObject getCustomCases()
{
return $"{methodInfo.Name} - { values[0] }";
return JObject.Parse(JsonTestHelpers.GetTestJson("custom-cases"));
}

[TestMethod]
[DynamicData(nameof(RunTests), DynamicDataSourceType.Method, DynamicDataDisplayName = nameof(GetTestNames))]
public void Run(string testname, Context context, Experiment experiment, JToken expectedValue, bool inExperiment, bool hashUsed)
public static string GetTestNames(MethodInfo methodInfo, object[] values)
{
if (testname is null)
{
throw new ArgumentNullException(nameof(testname));
}

GrowthBook.GrowthBook gb = new GrowthBook.GrowthBook(context);
ExperimentResult actual = gb.Run(experiment);
Assert.AreEqual(inExperiment, actual.InExperiment);
Assert.AreEqual(hashUsed, actual.HashUsed);
Assert.IsTrue(JToken.DeepEquals(actual.Value, expectedValue));
return $"{methodInfo.Name} - {values[0]}";
}
#endregion

#region data
public static IEnumerable<object[]> RunTests()
{
foreach (JArray testCase in (JArray)testCases["run"])
foreach (JArray testCase in (JArray)getStandardCases()["run"])
{
yield return new object[] {
testCase[0].ToString(),
Expand All @@ -63,95 +46,112 @@ public static IEnumerable<object[]> RunTests()
};
}
}
public static IEnumerable<object[]> EvalFeatureTests()
{
foreach (JArray testCase in (JArray)getStandardCases()["feature"])
{
yield return new object[] {
testCase[0].ToString(),
testCase[1].ToObject<Context>(),
testCase[2].ToString(),
testCase[3].ToObject<FeatureResult>(),
};
}
}
#endregion

[TestMethod]
[Fact]
public void Run_ShouldCallTrackingCallbackOnce()
{
JArray testCase = (JArray)customCases["run"];
JArray testCase = (JArray)getCustomCases()["run"];
int trackingCounter = 0;

Context context = testCase[0].ToObject<Context>();
context.TrackingCallback = (Experiment experiment, ExperimentResult result) =>
{
Assert.IsTrue(JToken.DeepEquals(result.Value, testCase[2]));
Assert.AreEqual(testCase[3].ToObject<bool>(), result.InExperiment);
Assert.AreEqual(testCase[4].ToObject<bool>(), result.HashUsed);
Assert.True(JToken.DeepEquals(result.Value, testCase[2]));
Assert.Equal(testCase[3].ToObject<bool>(), result.InExperiment);
Assert.Equal(testCase[4].ToObject<bool>(), result.HashUsed);
trackingCounter++;
};

GrowthBook.GrowthBook gb = new GrowthBook.GrowthBook(context);
GrowthBook gb = new GrowthBook(context);
gb.Run(testCase[1].ToObject<Experiment>());
gb.Run(testCase[1].ToObject<Experiment>());
Assert.AreEqual(1, trackingCounter);
Assert.Equal(1, trackingCounter);
}

[TestMethod]
[Fact]
public void Run_ShouldCallSubscribedCallbacks()
{
JArray testCase = (JArray)customCases["run"];
GrowthBook.GrowthBook gb = new GrowthBook.GrowthBook(testCase[0].ToObject<Context>());
JArray testCase = (JArray)getCustomCases()["run"];
GrowthBook gb = new GrowthBook(testCase[0].ToObject<Context>());

int subCounterOne = 0;
gb.Subscribe((Experiment experiment, ExperimentResult result) =>
{
Assert.IsTrue(JToken.DeepEquals(result.Value, testCase[2]));
Assert.AreEqual(testCase[3].ToObject<bool>(), result.InExperiment);
Assert.AreEqual(testCase[4].ToObject<bool>(), result.HashUsed);
Assert.True(JToken.DeepEquals(result.Value, testCase[2]));
Assert.Equal(testCase[3].ToObject<bool>(), result.InExperiment);
Assert.Equal(testCase[4].ToObject<bool>(), result.HashUsed);
subCounterOne++;
});

int subCounterTwo = 0;
Action unsubscribe = gb.Subscribe((Experiment experiment, ExperimentResult result) =>
{
Assert.IsTrue(JToken.DeepEquals(result.Value, testCase[2]));
Assert.AreEqual(testCase[3].ToObject<bool>(), result.InExperiment);
Assert.AreEqual(testCase[4].ToObject<bool>(), result.HashUsed);
Assert.True(JToken.DeepEquals(result.Value, testCase[2]));
Assert.Equal(testCase[3].ToObject<bool>(), result.InExperiment);
Assert.Equal(testCase[4].ToObject<bool>(), result.HashUsed);
subCounterTwo++;
});
unsubscribe();

int subCounterThree = 0;
gb.Subscribe((Experiment experiment, ExperimentResult result) =>
{
Assert.IsTrue(JToken.DeepEquals(result.Value, testCase[2]));
Assert.AreEqual(testCase[3].ToObject<bool>(), result.InExperiment);
Assert.AreEqual(testCase[4].ToObject<bool>(), result.HashUsed);
Assert.True(JToken.DeepEquals(result.Value, testCase[2]));
Assert.Equal(testCase[3].ToObject<bool>(), result.InExperiment);
Assert.Equal(testCase[4].ToObject<bool>(), result.HashUsed);
subCounterThree++;
});

gb.Run(testCase[1].ToObject<Experiment>());
gb.Run(testCase[1].ToObject<Experiment>());
gb.Run(testCase[1].ToObject<Experiment>());
Assert.AreEqual(1, subCounterOne);
Assert.AreEqual(0, subCounterTwo);
Assert.AreEqual(1, subCounterThree);
Assert.Equal(1, subCounterOne);
Assert.Equal(0, subCounterTwo);
Assert.Equal(1, subCounterThree);
}

[TestMethod]
[DynamicData(nameof(EvalFeatureTests), DynamicDataSourceType.Method, DynamicDataDisplayName = nameof(GetTestNames))]
public void EvalFeature(string testname, Context context, string key, FeatureResult expected)
[Theory]
[MemberData(nameof(RunTests))]
public void Run(string testname, Context context, Experiment experiment, JToken expectedValue, bool inExperiment, bool hashUsed)
{
if (testname is null)
{
throw new ArgumentNullException(nameof(testname));
}

GrowthBook.GrowthBook gb = new GrowthBook.GrowthBook(context);
FeatureResult actual = gb.EvalFeature(key);
Assert.AreEqual(expected, actual);
GrowthBook gb = new GrowthBook(context);
ExperimentResult actual = gb.Run(experiment);
Assert.Equal(inExperiment, actual.InExperiment);
Assert.Equal(hashUsed, actual.HashUsed);
Assert.True(JToken.DeepEquals(actual.Value, expectedValue));
}

public static IEnumerable<object[]> EvalFeatureTests()
[Theory]
[MemberData(nameof(EvalFeatureTests))]
public void EvalFeature(string testname, Context context, string key, FeatureResult expected)
{
foreach (JArray testCase in (JArray)testCases["feature"])
if (testname is null)
{
yield return new object[] {
testCase[0].ToString(),
testCase[1].ToObject<Context>(),
testCase[2].ToString(),
testCase[3].ToObject<FeatureResult>(),
};
throw new ArgumentNullException(nameof(testname));
}

GrowthBook gb = new GrowthBook(context);
FeatureResult actual = gb.EvalFeature(key);
Assert.Equal(expected, actual);
}

}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using System.IO;
using System.Reflection;

namespace Growthbook.Tests.Json;
namespace GrowthBook.Tests.Json;

public static class JsonTestHelpers
{
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,45 +1,51 @@
using System;
using System.Collections.Generic;
using GrowthBook;
using Growthbook.Tests.Json;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
using System.Reflection;

using GrowthBook.Tests.Json;

using Newtonsoft.Json;

namespace Test
using Xunit;

namespace GrowthBook.Tests
{
[TestClass]
public class NamespaceTupleConverterTests
{
[TestMethod]
[Fact]
public void CreateFromJson_NoFeatures_ShouldSucceed()
{
string json = JsonTestHelpers.GetTestJson("GrowthBookContext.NoFeatures");

var gb = JsonConvert.DeserializeObject<Context>(json);
}

[TestMethod]
[Fact]
public void CreateFromJson_WithFeatures_ShouldSucceed()
{
string json = JsonTestHelpers.GetTestJson("GrowthBookContext");

var gb = JsonConvert.DeserializeObject<Context>(json);
}

[TestMethod]
[Fact]
public void CreateFeaturesFromJson_WithFeatures_ShouldSucceed()
{
string json = JsonTestHelpers.GetTestJson("FeatureDictionary");

var gb = JsonConvert.DeserializeObject<Dictionary<string, Feature>>(json);
}

[TestMethod]
[Fact]
public void CreateFeaturesFromJson_OneFeatureWithNameSpace_ShouldSucceed()
{
string json = JsonTestHelpers.GetTestJson("SingleFeatureDictionary.WithNameSpace.");
string json = JsonTestHelpers.GetTestJson("SingleFeatureDictionary.WithNameSpace");

var gb = JsonConvert.DeserializeObject<Dictionary<string, Feature>>(json);
}


}

}
Loading

0 comments on commit 179b5fa

Please sign in to comment.