Skip to content

Commit d538306

Browse files
committed
refactor: improve acceptance test support abstractions and tweak scenarios
1 parent 2303583 commit d538306

14 files changed

Lines changed: 307 additions & 260 deletions

test/ScriptCs.Tests.Acceptance/CommandLine.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,25 @@ namespace ScriptCs.Tests.Acceptance
1010
public class CommandLine
1111
{
1212
[Scenario]
13-
public static void UnexpectedOption(ScriptDirectory directory, Exception exception)
13+
public static void UnexpectedOption(Exception exception)
1414
{
1515
var scenario = MethodBase.GetCurrentMethod().GetFullName();
1616

17-
"Given a script directory"
18-
.f(() => directory = new ScriptDirectory(scenario));
17+
"When I execute scriptcs with an unknown option"
18+
.f(() => exception = Record.Exception(() => ScriptCsExe.Run(
19+
new[]
20+
{
21+
"-unknownoption"
22+
},
23+
ScenarioDirectory.Create(scenario))));
1924

20-
"When I execute scriptcs.exe with an argument of '-unknownoption'"
21-
.f(() => exception = Record.Exception(() => directory.Execute("-unknownoption")));
25+
"Then scriptcs errors"
26+
.f(() => exception.ShouldBeType<ScriptCsException>());
2227

23-
"Then the process errors"
24-
.f(() => exception.ShouldNotBeNull());
25-
26-
"And an error message is shown regarding 'unknownoption'"
28+
"And I see an error message regarding the unknown option"
2729
.f(() => exception.Message.ShouldContain("unknownoption"));
2830

29-
"And usage is shown"
31+
"And I see scriptcs usage details"
3032
.f(() => exception.Message.ShouldContain("Usage:"));
3133
}
3234
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
namespace ScriptCs.Tests.Acceptance
2+
{
3+
using System.IO;
4+
using System.Reflection;
5+
using ScriptCs.Tests.Acceptance.Support;
6+
using Should;
7+
using Xbehave;
8+
9+
public static class DirectoryCleaning
10+
{
11+
[Scenario]
12+
public static void CleaningADirectory(ScenarioDirectory directory, string output)
13+
{
14+
var scenario = MethodBase.GetCurrentMethod().GetFullName();
15+
16+
"Given a directory"
17+
.f(() => directory = ScenarioDirectory.Create(scenario));
18+
19+
"And the directory has an installed package"
20+
.f(() => ScriptCsExe.Install("ScriptCs.Adder.Local", directory));
21+
22+
"And the directory has an assembly cache"
23+
.f(() => directory.WriteLine(Path.Combine(directory.Map(ScriptCsExe.DllCacheFolder), "foo.txt"), null));
24+
25+
"When I clean the directory"
26+
.f(() => ScriptCsExe.Clean(directory));
27+
28+
"Then the packages folder is removed"
29+
.f(() => Directory.Exists(directory.Map(ScriptCsExe.PackagesFolder)).ShouldBeFalse());
30+
31+
"And the assembly cache folder is removed"
32+
.f(() => Directory.Exists(directory.Map(ScriptCsExe.DllCacheFolder)).ShouldBeFalse());
33+
}
34+
}
35+
}

test/ScriptCs.Tests.Acceptance/PackageInstallation.cs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,30 @@
99
public static class PackageInstallation
1010
{
1111
[Scenario]
12-
public static void InstallingAPackage(ScriptDirectory directory, string output)
12+
public static void InstallingAPackage(ScenarioDirectory directory, string output)
1313
{
1414
var scenario = MethodBase.GetCurrentMethod().GetFullName();
1515

16-
"Given a script directory"
17-
.f(() => directory = new ScriptDirectory(scenario));
16+
"When I install ScriptCs.Adder"
17+
.f(() => ScriptCsExe.Install("ScriptCs.Adder.Local", directory = ScenarioDirectory.Create(scenario)));
1818

19-
"When I install ScriptCs.Adder.Local"
20-
.f(() => directory.Install("ScriptCs.Adder.Local"));
21-
22-
"Then the ScriptCs.Adder.Local NuGet package should be in the packages folder"
19+
"Then the ScriptCs.Adder NuGet package is added to the packages folder"
2320
.f(() => File.Exists(
2421
Path.Combine(
25-
directory.PackagesFolder,
22+
directory.Map(ScriptCsExe.PackagesFolder),
2623
"ScriptCs.Adder.Local.0.1.1/ScriptCs.Adder.Local.0.1.1.nupkg"))
2724
.ShouldBeTrue());
2825

29-
"And the ScriptCs.Adder.Local assembly should be in the packages folder"
26+
"And the ScriptCs.Adder assembly is extracted"
3027
.f(() => File.Exists(
3128
Path.Combine(
32-
directory.PackagesFolder,
29+
directory.Map(ScriptCsExe.PackagesFolder),
3330
"ScriptCs.Adder.Local.0.1.1/lib/net45/ScriptCs.Adder.dll"))
3431
.ShouldBeTrue());
3532

36-
"And the packages file should contain an entry for ScriptCs.Adder.Local"
37-
.f(() => File.ReadAllText(directory.PackagesFile).ShouldContain(
38-
@"<package id=""ScriptCs.Adder.Local"" version=""0.1.1"" targetFramework=""net45"" />"));
33+
"And ScriptCs.Adder is added to the packages file"
34+
.f(() => File.ReadAllText(directory.Map(ScriptCsExe.PackagesFile)).ShouldContain(
35+
@"<package id=""ScriptCs.Adder.Local"" version=""0.1.1"" targetFramework=""net45"" />"));
3936
}
4037
}
4138
}

test/ScriptCs.Tests.Acceptance/PackageSaving.cs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,23 @@
99
public static class PackageSaving
1010
{
1111
[Scenario]
12-
public static void SavingAPackage(ScriptDirectory directory, string output)
12+
public static void SavingAPackage(ScenarioDirectory directory, string output)
1313
{
1414
var scenario = MethodBase.GetCurrentMethod().GetFullName();
1515

16-
"Given a script directory"
17-
.f(() => directory = new ScriptDirectory(scenario));
16+
"When I install ScriptCs.Adder manually"
17+
.f(() =>
18+
{
19+
ScriptCsExe.Install("ScriptCs.Adder.Local", directory = ScenarioDirectory.Create(scenario));
20+
directory.DeleteFile(ScriptCsExe.PackagesFile);
21+
});
1822

19-
"When I install ScriptCs.Adder.Local manually"
20-
.f(() => directory.InstallManually("ScriptCs.Adder.Local"));
23+
"And I save packages"
24+
.f(() => ScriptCsExe.Save(directory));
2125

22-
"When I save the package"
23-
.f(() => directory.Save());
24-
25-
"Then packages file should contain an entry for ScriptCs.Adder.Local"
26-
.f(() => File.ReadAllText(directory.PackagesFile).ShouldContain(
27-
@"<package id=""ScriptCs.Adder.Local"" version=""0.1.1"" targetFramework=""net45"" />"));
26+
"Then ScriptCs.Adder is added to the packages file"
27+
.f(() => File.ReadAllText(directory.Map(ScriptCsExe.PackagesFile)).ShouldContain(
28+
@"<package id=""ScriptCs.Adder.Local"" version=""0.1.1"" targetFramework=""net45"" />"));
2829
}
2930
}
3031
}

test/ScriptCs.Tests.Acceptance/ScriptCs.Tests.Acceptance.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,14 @@
4444
<Link>Support\Guard.cs</Link>
4545
</Compile>
4646
<Compile Include="CommandLine.cs" />
47-
<Compile Include="WorkDirectoryCleaning.cs" />
47+
<Compile Include="Support\ScriptCsException.cs" />
48+
<Compile Include="DirectoryCleaning.cs" />
4849
<Compile Include="PackageSaving.cs" />
4950
<Compile Include="PackageInstallation.cs" />
5051
<Compile Include="ScriptPacks.cs" />
5152
<Compile Include="ScriptExecution.cs" />
5253
<Compile Include="Support\ScriptCsExe.cs" />
53-
<Compile Include="Support\ScriptDirectory.cs" />
54+
<Compile Include="Support\ScenarioDirectory.cs" />
5455
<Compile Include="Support\ProcessStartInfoExtensions.cs" />
5556
<Compile Include="Support\FileSystem.cs" />
5657
<Compile Include="Support\MethodBaseExtensions.cs" />

test/ScriptCs.Tests.Acceptance/ScriptExecution.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ public static class ScriptExecution
1212
[Scenario]
1313
[Example(true)]
1414
[Example(false)]
15-
public static void HelloWorld(bool debug, ScriptDirectory directory, string output)
15+
public static void HelloWorld(bool debug, ScenarioDirectory directory, string output)
1616
{
1717
var scenario = MethodBase.GetCurrentMethod().GetFullName();
1818

1919
"Given a hello world script"
20-
.f(() => directory = new ScriptDirectory(scenario)
20+
.f(() => directory = ScenarioDirectory.Create(scenario)
2121
.WriteLine("foo.csx", @"Console.WriteLine(""Hello world!"");"));
2222

2323
"When I execute the script with debug set to {0}"
24-
.f(() => output = directory.RunScript("foo.csx", debug));
24+
.f(() => output = ScriptCsExe.Run("foo.csx", debug, directory));
2525

2626
"Then I see 'Hello world!'"
2727
.f(() => output.ShouldContain("Hello world!"));
@@ -30,21 +30,22 @@ public static void HelloWorld(bool debug, ScriptDirectory directory, string outp
3030
[Scenario]
3131
[Example(true)]
3232
[Example(false)]
33-
public static void ScriptThrowsAnException(bool debug, ScriptDirectory directory, Exception ex)
33+
public static void ScriptThrowsAnException(bool debug, ScenarioDirectory directory, Exception exception)
3434
{
3535
var scenario = MethodBase.GetCurrentMethod().GetFullName();
3636

3737
"Given a script which throws an exception"
38-
.f(() => directory = new ScriptDirectory(scenario).WriteLine("foo.csx", @"throw new Exception(""BOOM!"");"));
38+
.f(() => directory = ScenarioDirectory.Create(scenario)
39+
.WriteLine("foo.csx", @"throw new Exception(""BOOM!"");"));
3940

4041
"When I execute the script with debug set to {0}"
41-
.f(() => ex = Record.Exception(() => directory.RunScript("foo.csx", debug)));
42+
.f(() => exception = Record.Exception(() => ScriptCsExe.Run("foo.csx", debug, directory)));
4243

43-
"Then the script fails"
44-
.f(() => ex.ShouldNotBeNull());
44+
"Then scriptcs fails"
45+
.f(() => exception.ShouldBeType<ScriptCsException>());
4546

4647
"And I see the exception message"
47-
.f(() => ex.Message.ShouldContain("BOOM!"));
48+
.f(() => exception.Message.ShouldContain("BOOM!"));
4849
}
4950
}
5051
}

test/ScriptCs.Tests.Acceptance/ScriptPacks.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@
88
public static class ScriptPacks
99
{
1010
[Scenario]
11-
public static void UsingAScriptPack(ScriptDirectory directory, string output)
11+
public static void UsingAScriptPack(ScenarioDirectory directory, string output)
1212
{
1313
var scenario = MethodBase.GetCurrentMethod().GetFullName();
1414

1515
"Given a script which uses ScriptCs.Adder to print the sum of 1234 and 5678"
16-
.f(() => directory = new ScriptDirectory(scenario).WriteLine(
17-
"foo.csx", @"Console.WriteLine(Require<Adder>().Add(1234, 5678));"));
16+
.f(() => directory = ScenarioDirectory.Create(scenario)
17+
.WriteLine("foo.csx", @"Console.WriteLine(Require<Adder>().Add(1234, 5678));"));
1818

19-
"When I install ScriptCs.Adder"
20-
.f(() => directory.Install("ScriptCs.Adder.Local"));
19+
"And ScriptCs.Adder is installed"
20+
.f(() => ScriptCsExe.Install("ScriptCs.Adder.Local", directory));
2121

22-
"And execute the script"
23-
.f(() => output = directory.RunScript("foo.csx"));
22+
"When execute the script"
23+
.f(() => output = ScriptCsExe.Run("foo.csx", directory));
2424

2525
"Then I see 6912"
2626
.f(() => output.ShouldContain("6912"));

test/ScriptCs.Tests.Acceptance/Support/FileSystem.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System;
44
using System.Globalization;
55
using System.IO;
6+
using Should;
67

78
// NOTE (adamralph): difficult to believe the retry stuff is required, but it is. System.IO and the filesystem race.
89
public static class FileSystem
@@ -100,5 +101,11 @@ public static void EnsureDirectoryDeleted(string path)
100101
break;
101102
}
102103
}
104+
105+
public static void EnsureFileDeleted(string fileName)
106+
{
107+
File.Delete(fileName);
108+
File.Exists(fileName).ShouldBeFalse(fileName + " should be deleted");
109+
}
103110
}
104111
}

test/ScriptCs.Tests.Acceptance/Support/ProcessStartInfoExtensions.cs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
{
33
using System;
44
using System.Diagnostics;
5-
using System.Globalization;
65
using System.IO;
76
using System.Text;
87

98
public static class ProcessStartInfoExtensions
109
{
11-
public static string Run(this ProcessStartInfo info, string logfile)
10+
public static Tuple<int, string> Run(this ProcessStartInfo info, string outputFile)
1211
{
1312
var output = new StringBuilder();
13+
int exitCode;
1414
using (var process = new Process())
1515
{
1616
process.StartInfo = info;
@@ -19,27 +19,31 @@ public static string Run(this ProcessStartInfo info, string logfile)
1919
process.Start();
2020
process.BeginOutputReadLine();
2121
process.BeginErrorReadLine();
22-
process.WaitForExit();
22+
if (!process.WaitForExit(30000))
23+
{
24+
try
25+
{
26+
process.Kill();
27+
}
28+
catch (Exception ex)
29+
{
30+
throw new TimeoutException(
31+
"The process took too longer than 30 seconds to exit and killing the process failed.", ex);
32+
}
33+
34+
throw new TimeoutException("The process took longer than 30 seconds to exit.");
35+
}
2336

24-
using (var writer = new StreamWriter(logfile, true))
37+
using (var writer = new StreamWriter(outputFile, true))
2538
{
2639
writer.WriteLine(output.ToString());
2740
writer.Flush();
2841
}
2942

30-
if (process.ExitCode != 0)
31-
{
32-
var message = string.Format(
33-
CultureInfo.InvariantCulture,
34-
"The process exited with code {0}. The output was: {1}",
35-
process.ExitCode.ToString(CultureInfo.InvariantCulture),
36-
output.ToString());
37-
38-
throw new InvalidOperationException(message);
39-
}
43+
exitCode = process.ExitCode;
4044
}
4145

42-
return output.ToString();
46+
return Tuple.Create(exitCode, output.ToString());
4347
}
4448
}
4549
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
namespace ScriptCs.Tests.Acceptance.Support
2+
{
3+
using System.IO;
4+
5+
public sealed class ScenarioDirectory
6+
{
7+
private static readonly string rootDirectory = "scenarios";
8+
9+
private readonly string _name;
10+
11+
public static ScenarioDirectory Create(string scenario)
12+
{
13+
var name = Path.Combine(rootDirectory, scenario);
14+
FileSystem.EnsureDirectoryDeleted(name);
15+
FileSystem.EnsureDirectoryCreated(name);
16+
return new ScenarioDirectory(name);
17+
}
18+
19+
private ScenarioDirectory(string name)
20+
{
21+
_name = name;
22+
}
23+
24+
public string Name
25+
{
26+
get { return _name; }
27+
}
28+
29+
public ScenarioDirectory WriteLine(string fileName, string text)
30+
{
31+
fileName = Map(fileName);
32+
FileSystem.EnsureDirectoryCreated(Path.GetDirectoryName(fileName));
33+
using (var writer = new StreamWriter(fileName, true))
34+
{
35+
writer.WriteLine(text);
36+
writer.Flush();
37+
}
38+
39+
return this;
40+
}
41+
42+
public void DeleteFile(string fileName)
43+
{
44+
FileSystem.EnsureFileDeleted(Map(fileName));
45+
}
46+
47+
public string Map(string path)
48+
{
49+
return Path.Combine(_name, path);
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)