diff --git a/appveyor.yml b/appveyor.yml
index be0c26c..4947040 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,7 +5,7 @@ skip_branch_with_pr: true
max_jobs: 1
configuration: Release
-image: Visual Studio 2017
+image: Visual Studio 2019
init:
- git config --global core.autocrlf input
@@ -29,8 +29,6 @@ test: off
test_script:
- ps: dotnet test --no-build
- - ps: dotnet test Tests/Snapper.Nunit.Tests/Snapper.Nunit.Tests.csproj --logger:Appveyor --no-build
- - ps: dotnet test Tests/Snapper.TestFrameworkSupport.Tests/Snapper.TestFrameworkSupport.Tests.csproj --logger:Appveyor --no-build
deploy:
- provider: NuGet
diff --git a/docs/pages/quickstart.md b/docs/pages/quickstart.md
index 7e5f689..cc3ec87 100644
--- a/docs/pages/quickstart.md
+++ b/docs/pages/quickstart.md
@@ -14,12 +14,13 @@ To run this quickstart, you need the following prerequisites:
```bash
nuget install Snapper
```
-2. Create an xUnit test like shown
+1. Create an xUnit test like shown
```csharp
public class MyTestClass {
[Fact]
- public void MyTest(){
+ public void MyTest()
+ {
var obj = new {
Key = "value"
};
@@ -28,42 +29,26 @@ public class MyTestClass {
}
}
```
+Run the test and you'll see that it passes.
The above code will try match the `obj` variable with a snapshot in the file `_snapshots/MyTestClass_MyTest.json` (relative to the file in which `MyTestClass` exists).
-For a new test this will fail as the file does not exist with an error similiar to this.
-```
-Snapper.Exceptions.SnapshotDoesNotExistException : A snapshot does not exist.
-Apply the [UpdateSnapshots] attribute on the test method or class and then run the test again to create a snapshot.
-```
-3. Lets create the snapshot so that the test passes. We could create the snapshot file manually if we wanted but that's a bit annoying. Luckily Snapper can generate a snapshot file for us! Apply the `[UpdateSnapshots]` attribute on the method and run the test again.
-```csharp
-public class MyTestClass {
-
- [UpdateSnapshots]
- [Fact]
- public void MyTest(){
- var obj = new {
- Key = "value"
- };
-
- obj.ShouldMatchSnapshot();
- }
-}
-```
+For a new test the snapshot file would not exist yet so Snapper automatically creates it on the first run.
+> Snapper automatically creates a new snapshot file for a new test from version v2.3.0 onwards. For previous versions use the `[UpdateSnapshots]` attribute to generate your initial snapshot.
-4. A file called `_snapshots/MyTestClass_MyTest.json` should have been created with the following content.
+1. A file called `_snapshots/MyTestClass_MyTest.json` should have been created with the following content.
```json
{
"Key": "value"
}
```
-You can now remove the `[UpdateSnapshots]` attribute on the method. You should also commit the `_snapshots/MyTestClass_MyTest.json` snapshot file with your source code.
+You should commit the `_snapshots/MyTestClass_MyTest.json` snapshot file with your source code.
-5. Lets make our test fail. Update your code to the following.
+1. Lets make our test fail due to a change in requirements. Update your code to the following.
```csharp
public class MyTestClass {
[Fact]
- public void MyTest(){
+ public void MyTest()
+ {
var obj = new {
Key = "My new value"
};
@@ -84,6 +69,23 @@ Run the test and you will see a nice error message showing the difference betwee
+ "Key": "My new value"
}
```
-You can then update the snapshot by adding the `[UpdateSnapshots]` attribute to the test and running it again or if the change was invalid fix the failing test.
+
+1. Once you've verified the new snapshot is expected you can update the snapshot by appling the `[UpdateSnapshots]` attribute on the method and then running the test again.
+```csharp
+public class MyTestClass {
+
+ [UpdateSnapshots]
+ [Fact]
+ public void MyTest()
+ {
+ var obj = new {
+ Key = "My new value"
+ };
+
+ obj.ShouldMatchSnapshot();
+ }
+}
+```
+This will update the snapshot file with the latest snapshot. Remember to remove the `[UpdateSnapshots]` attribute before you commit your code!
For more examples of tests written using Snapper see [here](https://github.com/theramis/Snapper/tree/master/project/Tests/Snapper.Tests).
\ No newline at end of file
diff --git a/project/Snapper/Attributes/UpdateSnapshotsAttribute.cs b/project/Snapper/Attributes/UpdateSnapshotsAttribute.cs
index b4835be..b01ea25 100644
--- a/project/Snapper/Attributes/UpdateSnapshotsAttribute.cs
+++ b/project/Snapper/Attributes/UpdateSnapshotsAttribute.cs
@@ -1,11 +1,11 @@
-using System;
+using System;
namespace Snapper.Attributes
{
///
///
/// Tells Snapper to update snapshots. Can be placed on methods, classes and assembly.
- /// Note: Has no effect when on inline snapshots
+ /// Note: Has no effect when using inline snapshots
///
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]
public class UpdateSnapshotsAttribute : Attribute
diff --git a/project/Snapper/Core/CIEnvironmentDetector.cs b/project/Snapper/Core/CIEnvironmentDetector.cs
new file mode 100644
index 0000000..0940dd6
--- /dev/null
+++ b/project/Snapper/Core/CIEnvironmentDetector.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Snapper.Core
+{
+ internal static class CiEnvironmentDetector
+ {
+ ///
+ /// Based on https://github.com/watson/ci-info/blob/2012259979fc38517f8e3fc74daff714251b554d/index.js#L52-L59
+ ///
+ private static IEnumerable CIEnvironmentVariables = new List
+ {
+ "CI", // Travis CI, CircleCI, Cirrus CI, Gitlab CI, Appveyor, CodeShip, dsari
+ "CONTINUOUS_INTEGRATION", // Travis CI, Cirrus CI
+ "BUILD_NUMBER", // Jenkins, TeamCity
+ "BUILD_BUILDNUMBER", // Azure DevOps
+ "RUN_ID" // TaskCluster, dsari
+ };
+
+ public static bool IsCiEnv()
+ {
+ foreach (var envVarTarget in new[] { EnvironmentVariableTarget.Process, EnvironmentVariableTarget.Machine, EnvironmentVariableTarget.User })
+ {
+ var found = CIEnvironmentVariables.Any(ciEnvironmentVariable =>
+ Environment.GetEnvironmentVariable(ciEnvironmentVariable, envVarTarget) != null);
+ if (found)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/project/Snapper/Core/Messages.cs b/project/Snapper/Core/Messages.cs
index d840552..7fa40ce 100644
--- a/project/Snapper/Core/Messages.cs
+++ b/project/Snapper/Core/Messages.cs
@@ -1,6 +1,5 @@
-using System;
+using System;
using System.Text;
-using Snapper.Attributes;
using Snapper.Json;
namespace Snapper.Core
@@ -12,12 +11,9 @@ public static string GetSnapResultMessage(SnapResult result)
switch (result.Status)
{
case SnapResultStatus.SnapshotDoesNotExist:
- var attributeName = nameof(UpdateSnapshotsAttribute).Replace("Attribute", string.Empty);
var message = new StringBuilder();
message.AppendLine($"A snapshot does not exist.{Environment.NewLine}");
- message.AppendLine($"Apply the [{attributeName}] attribute on the " +
- $"test method or class and then run the test again to " +
- $"create a snapshot.");
+ message.AppendLine("Run the test outside of a CI environment to create a snapshot.");
return message.ToString();
case SnapResultStatus.SnapshotsMatch:
return "Snapshots Match.";
diff --git a/project/Snapper/Core/SnapperCore.cs b/project/Snapper/Core/SnapperCore.cs
index 2e53c98..82422ee 100644
--- a/project/Snapper/Core/SnapperCore.cs
+++ b/project/Snapper/Core/SnapperCore.cs
@@ -17,10 +17,8 @@ internal class SnapperCore
protected SnapResult Snap(SnapshotId snapshotId, object newSnapshot)
{
var currentSnapshot = _snapshotStore.GetSnapshot(snapshotId);
- var areSnapshotsEqual = currentSnapshot != null
- && _snapshotComparer.CompareSnapshots(currentSnapshot, newSnapshot);
-
- if (!areSnapshotsEqual && _snapshotUpdateDecider.ShouldUpdateSnapshot())
+
+ if (ShouldUpdateSnapshot(currentSnapshot, newSnapshot))
{
_snapshotStore.StoreSnapshot(snapshotId, newSnapshot);
return SnapResult.SnapshotUpdated(currentSnapshot, newSnapshot);
@@ -31,9 +29,27 @@ protected SnapResult Snap(SnapshotId snapshotId, object newSnapshot)
return SnapResult.SnapshotDoesNotExist(newSnapshot);
}
- return areSnapshotsEqual
+ return _snapshotComparer.CompareSnapshots(currentSnapshot, newSnapshot)
? SnapResult.SnapshotsMatch(currentSnapshot, newSnapshot)
: SnapResult.SnapshotsDoNotMatch(currentSnapshot, newSnapshot);
}
+
+ private bool ShouldUpdateSnapshot(object currentSnapshot, object newSnapshot)
+ {
+ var snapshotsAreEqual = currentSnapshot != null
+ && _snapshotComparer.CompareSnapshots(currentSnapshot, newSnapshot);
+ if (!snapshotsAreEqual && _snapshotUpdateDecider.ShouldUpdateSnapshot())
+ {
+ return true;
+ }
+
+ // Create snapshot if it doesn't currently exist and its not a CI env
+ if (currentSnapshot == null)
+ {
+ return !CiEnvironmentDetector.IsCiEnv();
+ }
+
+ return false;
+ }
}
}
diff --git a/project/Snapper/Core/SnapshotUpdateDecider.cs b/project/Snapper/Core/SnapshotUpdateDecider.cs
index d18f5dc..2da371b 100644
--- a/project/Snapper/Core/SnapshotUpdateDecider.cs
+++ b/project/Snapper/Core/SnapshotUpdateDecider.cs
@@ -13,18 +13,6 @@ internal class SnapshotUpdateDecider : ISnapshotUpdateDecider
private const string UpdateSnapshotEnvironmentVariableName = "UpdateSnapshots";
private readonly string _envVarName;
- ///
- /// Based on https://github.com/watson/ci-info/blob/2012259979fc38517f8e3fc74daff714251b554d/index.js#L52-L59
- ///
- private readonly IEnumerable _ciEnvironmentVariables = new List
- {
- "CI", // Travis CI, CircleCI, Cirrus CI, Gitlab CI, Appveyor, CodeShip, dsari
- "CONTINUOUS_INTEGRATION", // Travis CI, Cirrus CI
- "BUILD_NUMBER", // Jenkins, TeamCity
- "BUILD_BUILDNUMBER", // Azure DevOps
- "RUN_ID" // TaskCluster, dsari
- };
-
public SnapshotUpdateDecider(ITestMethodResolver testMethodResolver,
string envVarName = UpdateSnapshotEnvironmentVariableName)
{
@@ -59,22 +47,7 @@ private bool ShouldUpdateSnapshotBasedOnAttribute()
{
if (TryGetUpdateSnapshotsAttribute(customAttributeProvider, out var att))
{
- return !(att.IgnoreIfCi && IsCiEnv());
- }
- }
-
- return false;
- }
-
- private bool IsCiEnv()
- {
- foreach (var envVarTarget in new[] { EnvironmentVariableTarget.Process, EnvironmentVariableTarget.Machine, EnvironmentVariableTarget.User})
- {
- var found = _ciEnvironmentVariables.Any(ciEnvironmentVariable =>
- Environment.GetEnvironmentVariable(ciEnvironmentVariable, envVarTarget) != null);
- if (found)
- {
- return true;
+ return !(att.IgnoreIfCi && CiEnvironmentDetector.IsCiEnv());
}
}
diff --git a/project/Tests/Snapper.Internals.Tests/Core/SnapperCoreTests.cs b/project/Tests/Snapper.Internals.Tests/Core/SnapperCoreTests.cs
index 6dc5c50..6ca7ff1 100644
--- a/project/Tests/Snapper.Internals.Tests/Core/SnapperCoreTests.cs
+++ b/project/Tests/Snapper.Internals.Tests/Core/SnapperCoreTests.cs
@@ -1,4 +1,5 @@
-using FluentAssertions;
+using System;
+using FluentAssertions;
using Moq;
using Snapper.Core;
using Xunit;
@@ -117,8 +118,26 @@ public void SnapshotDoesNotExist_ShouldUpdate_ResultStatusIs_SnapshotUpdated()
}
[Fact]
- public void SnapshotDoesNotExist_ResultStatusIs_SnapshotDoesNotExist()
+ public void SnapshotDoesNotExist_ResultStatusIs_SnapshotUpdated()
{
+ // Tests run on CI so clearing the CI environment variable to emulate local machine
+ Environment.SetEnvironmentVariable("CI", null, EnvironmentVariableTarget.Process);
+
+ _store.Setup(a => a.GetSnapshot(It.IsAny())).Returns(null);
+ _updateDecider.Setup(a => a.ShouldUpdateSnapshot()).Returns(false);
+
+ var result = _snapper.Snap(new SnapshotId("name", null, null, null), _obj);
+
+ _store.Verify(a => a.StoreSnapshot(It.IsAny(), It.IsAny