Skip to content

Commit 559a0e3

Browse files
authored
Merge pull request #22 from geeklearningio/release/0.3.2
Release/0.3.2
2 parents d4e804f + f94c98b commit 559a0e3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+342
-143
lines changed

.vscode/launch.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
// Use IntelliSense to find out which attributes exist for C# debugging
3+
// Use hover for the description of the existing attributes
4+
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": ".NET Core Launch (console)",
9+
"type": "coreclr",
10+
"request": "launch",
11+
"preLaunchTask": "build",
12+
// If you have changed target frameworks, make sure to update the program path.
13+
"program": "${workspaceRoot}/sample/Sample.Test/bin/Debug/netcoreapp1.1/Sample.Test.dll",
14+
"args": [],
15+
"cwd": "${workspaceRoot}/sample/Sample.Test",
16+
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
17+
"console": "internalConsole",
18+
"stopAtEntry": false,
19+
"internalConsoleOptions": "openOnSessionStart"
20+
},
21+
{
22+
"name": ".NET Core Attach",
23+
"type": "coreclr",
24+
"request": "attach",
25+
"processId": "${command:pickProcess}"
26+
}
27+
]
28+
}

.vscode/tasks.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"version": "0.1.0",
3+
"command": "dotnet",
4+
"isShellCommand": true,
5+
"args": [],
6+
"tasks": [
7+
{
8+
"taskName": "build",
9+
"args": [
10+
"${workspaceRoot}/sample/Sample.Test/Sample.Test.csproj"
11+
],
12+
"isBuildCommand": true,
13+
"problemMatcher": "$msCompile"
14+
}
15+
]
16+
}

GeekLearning.Test.Integration.sln renamed to GeekLearning.Testavior.sln

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
4-
VisualStudioVersion = 15.0.26228.9
4+
VisualStudioVersion = 15.0.26430.6
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{033A6692-6022-469D-A0E7-B9C636CA05A8}"
77
EndProject
88
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "items", "items", "{54842458-42F9-4A49-A286-83AA1071184A}"
99
ProjectSection(SolutionItems) = preProject
1010
.gitignore = .gitignore
11-
NuGet.Config = NuGet.Config
11+
global.json = global.json
12+
README.md = README.md
1213
EndProjectSection
1314
EndProject
1415
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{36903259-F63B-480F-9F84-005D0A2BA8DA}"
1516
EndProject
1617
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "specflow", "specflow", "{D6AF528A-BA8D-47D7-BAD0-810154BB0FD9}"
1718
EndProject
18-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeekLearning.Test.Integration", "src\GeekLearning.Test.Integration\GeekLearning.Test.Integration.csproj", "{F28C9E50-7EB0-4368-9812-8EE693648E78}"
19+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeekLearning.Testavior", "src\GeekLearning.Testavior\GeekLearning.Testavior.csproj", "{F28C9E50-7EB0-4368-9812-8EE693648E78}"
1920
EndProject
20-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeekLearning.Test.Configuration", "src\GeekLearning.Test.Configuration\GeekLearning.Test.Configuration.csproj", "{9146CE74-6610-472E-8FC8-3AEF733868D0}"
21+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeekLearning.Testavior.Configuration", "src\GeekLearning.Testavior.Configuration\GeekLearning.Testavior.Configuration.csproj", "{9146CE74-6610-472E-8FC8-3AEF733868D0}"
2122
EndProject
2223
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Test.Splecflow", "sample\Sample.Test.Splecflow\Sample.Test.Splecflow.csproj", "{8EF01F44-FDCC-4E25-8519-2D93C450379A}"
2324
EndProject

README.md

Lines changed: 155 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,156 @@
1-
# gl-dotnet-test-integration
2-
[.NET Core 1.0] Library to help implement integration testing.
1+
# Testavior
2+
*Testavior* is a set of [NuGet libraries]() to help you develop **Behavior** Tests for **ASP.NET Core**.
33

4-
Coming soon !
4+
>Behavior Tests are a way of testing your application features applying different types of behaviors to cover a **functional scenario**.
5+
6+
It provides a simple and efficient approach to write automated tests for your ASP.NET Core application.
7+
For more information about *Behavior Testing* with ASP.NET Core, please take a look here http://geeklearning.io/a-different-approach-to-test-your-asp-net-core-application
8+
9+
### Features
10+
*Testavior* provides 2 libraries:
11+
* **Configuration**: Helps you configure your application to easily integrate behavior tests for your scenarios.
12+
* **Integration**: Provides a featured and highly configurable test environment for your behavior tests:
13+
* Configured Test WebHost
14+
* Configured authentication context
15+
* Test authentication middleware
16+
* Configurable test identity
17+
* Identity claims helper
18+
* Configured Entity Framework Core context using SQLite provider
19+
* Serialization helper to handle URL encoded content
20+
* Set of HTTP tools to handle *CSRF* protection (very useful to test edition scenarios)
21+
* Assertion helper
22+
23+
### Installation
24+
On your ASP.NET Core project
25+
* Install the **GeekLearning.SceneTest.Configuration** nuget package
26+
```
27+
> dotnet add package GeekLearning.Testavior.Configuration
28+
```
29+
30+
On your .NET Core Unit Test project
31+
* Install the **GeekLearning.SceneTest** nuget package
32+
```
33+
> dotnet add package GeekLearning.Testavior
34+
```
35+
* Add your ASP.NET Core web project as a project reference
36+
### Configuration
37+
The Test environment provided by *SceneTest* is based on a **Startup Configuration Service** that let you separate the **Production** environment configuration from the **Test** environment configuration.
38+
This configuration service is represented by a contract **IStartupConfigurationService** which define 3 methods: *Configure, ConfigureEnvironment, ConfigureService* that have to be called within the **Startup Routine** to inject environment dependent configuration.
39+
40+
1 - In your **ASP.NET Core** project:
41+
* Add a *StartupConfigurationService* class (change name if you wish) to your web project.
42+
* Implement the **IStartupConfigurationService** interface (optionally, inherit from *DefaultStartupConfigurationService* to use the default empty implementation)
43+
* Implement the configuration specific to the Production environment and which must not be executed in the Test environment:
44+
* *ConfigureServices*: implement the configuration options that are specific to the Production environment
45+
* *Configure*: implement the *middleware* configuration specific to the Production environment
46+
* *ConfigureEnvironment*: implement what has to be executed before anything
47+
48+
Sample:
49+
```csharp
50+
public class StartupConfigurationService : DefaultStartupConfigurationService
51+
{
52+
public override void ConfigureServices(IServiceCollection services, IConfigurationRoot configuration)
53+
{
54+
base.ConfigureServices(services, configuration);
55+
56+
var connection = "CONNECTION_STRING";
57+
58+
services.AddDbContext<Data.BloggingContext>(options =>
59+
options.UseSqlServer(connection));
60+
}
61+
}
62+
```
63+
64+
2 - In your **Program** class:
65+
Inject your *StartupConfigurationService* by calling the **ConfigureStartup** method on your **WebHostBuilder**:
66+
```csharp
67+
new WebHostBuilder()
68+
...
69+
.UseStartup<Startup>()
70+
.ConfigureStartup<StartupConfigurationService>()
71+
```
72+
73+
3 - In your **Startup** class:
74+
* Inject the *IStartupConfigurationService* interface into the Startup class
75+
* Call the *ConfigureEnvironment* method at the end of the Startup constructor
76+
* Call the *ConfigureServices* method at the end of the original Startup ConfigureServices method
77+
* Call the *Configure* method at the beginning of the original Startup Configure method
78+
79+
Sample:
80+
```csharp
81+
public class Startup
82+
{
83+
private IStartupConfigurationService externalStartupConfiguration;
84+
85+
public Startup(IHostingEnvironment env, IStartupConfigurationService externalStartupConfiguration = null)
86+
{
87+
this.externalStartupConfiguration = externalStartupConfiguration;
88+
this.externalStartupConfiguration.ConfigureEnvironment(env);
89+
}
90+
91+
public void ConfigureServices(IServiceCollection services)
92+
{
93+
services.AddMvc()
94+
95+
// Pass configuration (IConfigurationRoot) to the configuration service if needed
96+
this.externalStartupConfiguration.ConfigureServices(services, null);
97+
}
98+
99+
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
100+
{
101+
this.externalStartupConfiguration.Configure(app, env, loggerFactory);
102+
103+
app.UseMvc();
104+
}
105+
}
106+
```
107+
108+
109+
### Writing Tests
110+
A specific *IStartupConfigurationService* is required for the **Test** environment if you want to implement **Test Specific** configuration.
111+
*Testavior* comes with a test specific *IStartupConfigurationService* implementation: **TestStartupConfigurationService** which provide a **Test Environment** full of useful features (see **Features** section).
112+
Of course you can implement your own *Test StartupConfigurationService* (by using the onboard TestStartupConfigurationService or not).
113+
114+
To create a *Test Environment*, just instanciate the **TestEnvironment** class by passing it your ASP.NET Core application *Startup*, your *IStartupConfigurationService* implementation and the type of your EF Core ObjectContext
115+
```csharp
116+
var testEnvironment = new TestEnvironment<Startup, TestStartupConfigurationService<[EF_DB_CONTEXT]>>(
117+
Path.Combine(System.AppContext.BaseDirectory, @"[PATH_TO_WEB_APP]"));
118+
```
119+
120+
#### API Test
121+
Write your API test by just sending web requests using the *Test Environment*:
122+
```csharp
123+
var response = testEnvironment.Client.GetAsync("/api/data").Result;
124+
response.EnsureSuccessStatusCode();
125+
126+
// Test result content
127+
var result = JsonConvert.DeserializeObject<Data[]>(response.Content.ReadAsStringAsync().Result);
128+
129+
Assert.AreEqual("data", result.Data);
130+
...
131+
```
132+
133+
#### MVC Test
134+
Write a MVC test is almost as easy as testing an API except that you might want to test the **Model** returned by the server and not the **View**.
135+
To do that, *Testavior* provides a **ViewModelRepository** that will intercept and store the view's models returned by the server.
136+
137+
You can access to the this repository using the ASP.NET Core dependency injection mechanism:
138+
139+
```csharp
140+
[TestMethod]
141+
public void Mvc_GetBlogsShouldBeOk()
142+
{
143+
base.TestEnvironment.Client.GetAsync("/").Result.EnsureSuccessStatusCode();
144+
145+
var viewModel = base.TestEnvironment
146+
.ServiceProvider
147+
.GetRequiredService<ViewModelRepository>()
148+
.Get<[VIEWMODEL_TYPE]>();
149+
150+
Assert.AreEqual("data", viewModel.Data);
151+
}
152+
```
153+
154+
And feel free to take a look at the [Samples](https://github.com/geeklearningio/gl-dotnet-test-integration/tree/develop/sample) section ;)
155+
156+
Happy testing ! :)

global.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"projects": [ "src", "sample" ],
3+
"sdk": {
4+
"version": "1.0.4"
5+
}
6+
}

sample/Sample.Test.Splecflow/Api/GetBlogs/GetBlogs.steps.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
namespace GeekLearning.Test.Integration.Sample.Test.GetBlogs.Api
22
{
3-
using Data;
4-
using Environment;
5-
using Newtonsoft.Json;
6-
using System.Collections.Generic;
7-
using System.Net.Http;
3+
using GeekLearning.Testavior;
4+
using GeekLearning.Testavior.Environment;
5+
using GeekLearning.Testavior.Sample.Data;
6+
using Newtonsoft.Json;
7+
using System.Collections.Generic;
88
using TechTalk.SpecFlow;
99
using TechTalk.SpecFlow.Assist;
1010

sample/Sample.Test.Splecflow/MainSteps.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace GeekLearning.Test.Integration.Sample.Test
1+
namespace GeekLearning.Testavior.Sample.Test
22
{
33
using Data;
44
using Environment;

sample/Sample.Test.Splecflow/Mvc/CreateBlog/CreateBlog.steps.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
namespace GeekLearning.Test.Integration.Sample.Test.Mvc.CreateBlog
22
{
3-
using Environment;
3+
using GeekLearning.Testavior.Environment;
4+
using GeekLearning.Testavior.Sample.Data;
45
using Microsoft.Extensions.DependencyInjection;
56
using Microsoft.VisualStudio.TestTools.UnitTesting;
6-
using System;
77
using System.Linq;
88
using System.Net.Http;
99
using TechTalk.SpecFlow;
@@ -16,7 +16,7 @@ public void WhenICreateANewBlog(string blogUrl)
1616
{
1717
ScenarioContext.Current.Get<ITestEnvironment>("TestEnvironment")
1818
.Client
19-
.PostAsJsonAntiForgeryAsync("blogs/create", new Data.Blog { Url = blogUrl }).Wait();
19+
.PostAsJsonAntiForgeryAsync("blogs/create", new Blog { Url = blogUrl }).Wait();
2020
}
2121

2222
[Then(@"the blog '(.*)' must be created")]
@@ -25,7 +25,7 @@ public void ThenTheBlogMustBeCreated(string blogUrl)
2525
using (var serviceScope = ScenarioContext.Current.Get<ITestEnvironment>("TestEnvironment").ServiceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
2626
{
2727
Assert.IsNotNull(serviceScope.ServiceProvider
28-
.GetService<Data.BloggingContext>()
28+
.GetService<BloggingContext>()
2929
.Blogs
3030
.FirstOrDefault(b => b.Url == blogUrl));
3131
}

sample/Sample.Test.Splecflow/Mvc/GetBlogs/GetBlogs.steps.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
namespace GeekLearning.Test.Integration.Sample.Test.GetBlogs.Mvc
22
{
3-
using Data;
4-
using Environment;
5-
using Integration.Mvc;
3+
using GeekLearning.Testavior;
4+
using GeekLearning.Testavior.Environment;
5+
using GeekLearning.Testavior.Mvc;
6+
using GeekLearning.Testavior.Sample.Data;
67
using Microsoft.Extensions.DependencyInjection;
78
using System.Collections.Generic;
89
using TechTalk.SpecFlow;

sample/Sample.Test.Splecflow/Sample.Test.Splecflow.csproj

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<ProjectReference Include="..\..\src\GeekLearning.Test.Integration\GeekLearning.Test.Integration.csproj" />
11+
<ProjectReference Include="..\..\src\GeekLearning.Testavior\GeekLearning.Testavior.csproj" />
1212
<ProjectReference Include="..\Sample.Web\Sample.Web.csproj" />
1313
</ItemGroup>
1414

1515
<ItemGroup>
1616
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
17-
<PackageReference Include="MSTest.TestAdapter" Version="1.1.13" />
18-
<PackageReference Include="MSTest.TestFramework" Version="1.1.13" />
17+
<PackageReference Include="MSTest.TestAdapter" Version="1.1.14" />
18+
<PackageReference Include="MSTest.TestFramework" Version="1.1.14" />
1919
<PackageReference Include="SpecFlow" Version="2.1.0" />
2020
<PackageReference Include="SpecFlow.NetCore" Version="1.0.0-rc8" />
2121
</ItemGroup>
@@ -24,9 +24,9 @@
2424
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
2525
</ItemGroup>
2626

27-
<Target Name="PrecompileScript" BeforeTargets="BeforeBuild">
28-
<Exec Command="dotnet SpecFlow.NetCore" />
29-
</Target>
27+
<Target Name="PrecompileScript" BeforeTargets="BeforeBuild">
28+
<Exec Command="dotnet SpecFlow.NetCore" />
29+
</Target>
3030

3131
<ItemGroup>
3232
<DotNetCliToolReference Include="SpecFlow.NetCore" Version="1.0.0-rc8" />

0 commit comments

Comments
 (0)