Skip to content

Commit

Permalink
Merge pull request #22 from geeklearningio/release/0.3.2
Browse files Browse the repository at this point in the history
Release/0.3.2
  • Loading branch information
arnaudauroux authored May 26, 2017
2 parents d4e804f + f94c98b commit 559a0e3
Show file tree
Hide file tree
Showing 48 changed files with 342 additions and 143 deletions.
28 changes: 28 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceRoot}/sample/Sample.Test/bin/Debug/netcoreapp1.1/Sample.Test.dll",
"args": [],
"cwd": "${workspaceRoot}/sample/Sample.Test",
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
"console": "internalConsole",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}
16 changes: 16 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"version": "0.1.0",
"command": "dotnet",
"isShellCommand": true,
"args": [],
"tasks": [
{
"taskName": "build",
"args": [
"${workspaceRoot}/sample/Sample.Test/Sample.Test.csproj"
],
"isBuildCommand": true,
"problemMatcher": "$msCompile"
}
]
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.9
VisualStudioVersion = 15.0.26430.6
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{033A6692-6022-469D-A0E7-B9C636CA05A8}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "items", "items", "{54842458-42F9-4A49-A286-83AA1071184A}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
NuGet.Config = NuGet.Config
global.json = global.json
README.md = README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{36903259-F63B-480F-9F84-005D0A2BA8DA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "specflow", "specflow", "{D6AF528A-BA8D-47D7-BAD0-810154BB0FD9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeekLearning.Test.Integration", "src\GeekLearning.Test.Integration\GeekLearning.Test.Integration.csproj", "{F28C9E50-7EB0-4368-9812-8EE693648E78}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeekLearning.Testavior", "src\GeekLearning.Testavior\GeekLearning.Testavior.csproj", "{F28C9E50-7EB0-4368-9812-8EE693648E78}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeekLearning.Test.Configuration", "src\GeekLearning.Test.Configuration\GeekLearning.Test.Configuration.csproj", "{9146CE74-6610-472E-8FC8-3AEF733868D0}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeekLearning.Testavior.Configuration", "src\GeekLearning.Testavior.Configuration\GeekLearning.Testavior.Configuration.csproj", "{9146CE74-6610-472E-8FC8-3AEF733868D0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Test.Splecflow", "sample\Sample.Test.Splecflow\Sample.Test.Splecflow.csproj", "{8EF01F44-FDCC-4E25-8519-2D93C450379A}"
EndProject
Expand Down
158 changes: 155 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,156 @@
# gl-dotnet-test-integration
[.NET Core 1.0] Library to help implement integration testing.
# Testavior
*Testavior* is a set of [NuGet libraries]() to help you develop **Behavior** Tests for **ASP.NET Core**.

Coming soon !
>Behavior Tests are a way of testing your application features applying different types of behaviors to cover a **functional scenario**.
It provides a simple and efficient approach to write automated tests for your ASP.NET Core application.
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

### Features
*Testavior* provides 2 libraries:
* **Configuration**: Helps you configure your application to easily integrate behavior tests for your scenarios.
* **Integration**: Provides a featured and highly configurable test environment for your behavior tests:
* Configured Test WebHost
* Configured authentication context
* Test authentication middleware
* Configurable test identity
* Identity claims helper
* Configured Entity Framework Core context using SQLite provider
* Serialization helper to handle URL encoded content
* Set of HTTP tools to handle *CSRF* protection (very useful to test edition scenarios)
* Assertion helper

### Installation
On your ASP.NET Core project
* Install the **GeekLearning.SceneTest.Configuration** nuget package
```
> dotnet add package GeekLearning.Testavior.Configuration
```

On your .NET Core Unit Test project
* Install the **GeekLearning.SceneTest** nuget package
```
> dotnet add package GeekLearning.Testavior
```
* Add your ASP.NET Core web project as a project reference
### Configuration
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.
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.

1 - In your **ASP.NET Core** project:
* Add a *StartupConfigurationService* class (change name if you wish) to your web project.
* Implement the **IStartupConfigurationService** interface (optionally, inherit from *DefaultStartupConfigurationService* to use the default empty implementation)
* Implement the configuration specific to the Production environment and which must not be executed in the Test environment:
* *ConfigureServices*: implement the configuration options that are specific to the Production environment
* *Configure*: implement the *middleware* configuration specific to the Production environment
* *ConfigureEnvironment*: implement what has to be executed before anything

Sample:
```csharp
public class StartupConfigurationService : DefaultStartupConfigurationService
{
public override void ConfigureServices(IServiceCollection services, IConfigurationRoot configuration)
{
base.ConfigureServices(services, configuration);

var connection = "CONNECTION_STRING";

services.AddDbContext<Data.BloggingContext>(options =>
options.UseSqlServer(connection));
}
}
```

2 - In your **Program** class:
Inject your *StartupConfigurationService* by calling the **ConfigureStartup** method on your **WebHostBuilder**:
```csharp
new WebHostBuilder()
...
.UseStartup<Startup>()
.ConfigureStartup<StartupConfigurationService>()
```

3 - In your **Startup** class:
* Inject the *IStartupConfigurationService* interface into the Startup class
* Call the *ConfigureEnvironment* method at the end of the Startup constructor
* Call the *ConfigureServices* method at the end of the original Startup ConfigureServices method
* Call the *Configure* method at the beginning of the original Startup Configure method

Sample:
```csharp
public class Startup
{
private IStartupConfigurationService externalStartupConfiguration;

public Startup(IHostingEnvironment env, IStartupConfigurationService externalStartupConfiguration = null)
{
this.externalStartupConfiguration = externalStartupConfiguration;
this.externalStartupConfiguration.ConfigureEnvironment(env);
}

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()

// Pass configuration (IConfigurationRoot) to the configuration service if needed
this.externalStartupConfiguration.ConfigureServices(services, null);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
this.externalStartupConfiguration.Configure(app, env, loggerFactory);

app.UseMvc();
}
}
```


### Writing Tests
A specific *IStartupConfigurationService* is required for the **Test** environment if you want to implement **Test Specific** configuration.
*Testavior* comes with a test specific *IStartupConfigurationService* implementation: **TestStartupConfigurationService** which provide a **Test Environment** full of useful features (see **Features** section).
Of course you can implement your own *Test StartupConfigurationService* (by using the onboard TestStartupConfigurationService or not).

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
```csharp
var testEnvironment = new TestEnvironment<Startup, TestStartupConfigurationService<[EF_DB_CONTEXT]>>(
Path.Combine(System.AppContext.BaseDirectory, @"[PATH_TO_WEB_APP]"));
```

#### API Test
Write your API test by just sending web requests using the *Test Environment*:
```csharp
var response = testEnvironment.Client.GetAsync("/api/data").Result;
response.EnsureSuccessStatusCode();

// Test result content
var result = JsonConvert.DeserializeObject<Data[]>(response.Content.ReadAsStringAsync().Result);

Assert.AreEqual("data", result.Data);
...
```

#### MVC Test
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**.
To do that, *Testavior* provides a **ViewModelRepository** that will intercept and store the view's models returned by the server.

You can access to the this repository using the ASP.NET Core dependency injection mechanism:

```csharp
[TestMethod]
public void Mvc_GetBlogsShouldBeOk()
{
base.TestEnvironment.Client.GetAsync("/").Result.EnsureSuccessStatusCode();

var viewModel = base.TestEnvironment
.ServiceProvider
.GetRequiredService<ViewModelRepository>()
.Get<[VIEWMODEL_TYPE]>();

Assert.AreEqual("data", viewModel.Data);
}
```

And feel free to take a look at the [Samples](https://github.com/geeklearningio/gl-dotnet-test-integration/tree/develop/sample) section ;)

Happy testing ! :)
6 changes: 6 additions & 0 deletions global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"projects": [ "src", "sample" ],
"sdk": {
"version": "1.0.4"
}
}
10 changes: 5 additions & 5 deletions sample/Sample.Test.Splecflow/Api/GetBlogs/GetBlogs.steps.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
namespace GeekLearning.Test.Integration.Sample.Test.GetBlogs.Api
{
using Data;
using Environment;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Net.Http;
using GeekLearning.Testavior;
using GeekLearning.Testavior.Environment;
using GeekLearning.Testavior.Sample.Data;
using Newtonsoft.Json;
using System.Collections.Generic;
using TechTalk.SpecFlow;
using TechTalk.SpecFlow.Assist;

Expand Down
2 changes: 1 addition & 1 deletion sample/Sample.Test.Splecflow/MainSteps.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace GeekLearning.Test.Integration.Sample.Test
namespace GeekLearning.Testavior.Sample.Test
{
using Data;
using Environment;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
namespace GeekLearning.Test.Integration.Sample.Test.Mvc.CreateBlog
{
using Environment;
using GeekLearning.Testavior.Environment;
using GeekLearning.Testavior.Sample.Data;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using System.Net.Http;
using TechTalk.SpecFlow;
Expand All @@ -16,7 +16,7 @@ public void WhenICreateANewBlog(string blogUrl)
{
ScenarioContext.Current.Get<ITestEnvironment>("TestEnvironment")
.Client
.PostAsJsonAntiForgeryAsync("blogs/create", new Data.Blog { Url = blogUrl }).Wait();
.PostAsJsonAntiForgeryAsync("blogs/create", new Blog { Url = blogUrl }).Wait();
}

[Then(@"the blog '(.*)' must be created")]
Expand All @@ -25,7 +25,7 @@ public void ThenTheBlogMustBeCreated(string blogUrl)
using (var serviceScope = ScenarioContext.Current.Get<ITestEnvironment>("TestEnvironment").ServiceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
Assert.IsNotNull(serviceScope.ServiceProvider
.GetService<Data.BloggingContext>()
.GetService<BloggingContext>()
.Blogs
.FirstOrDefault(b => b.Url == blogUrl));
}
Expand Down
7 changes: 4 additions & 3 deletions sample/Sample.Test.Splecflow/Mvc/GetBlogs/GetBlogs.steps.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
namespace GeekLearning.Test.Integration.Sample.Test.GetBlogs.Mvc
{
using Data;
using Environment;
using Integration.Mvc;
using GeekLearning.Testavior;
using GeekLearning.Testavior.Environment;
using GeekLearning.Testavior.Mvc;
using GeekLearning.Testavior.Sample.Data;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using TechTalk.SpecFlow;
Expand Down
12 changes: 6 additions & 6 deletions sample/Sample.Test.Splecflow/Sample.Test.Splecflow.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\GeekLearning.Test.Integration\GeekLearning.Test.Integration.csproj" />
<ProjectReference Include="..\..\src\GeekLearning.Testavior\GeekLearning.Testavior.csproj" />
<ProjectReference Include="..\Sample.Web\Sample.Web.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.1.13" />
<PackageReference Include="MSTest.TestFramework" Version="1.1.13" />
<PackageReference Include="MSTest.TestAdapter" Version="1.1.14" />
<PackageReference Include="MSTest.TestFramework" Version="1.1.14" />
<PackageReference Include="SpecFlow" Version="2.1.0" />
<PackageReference Include="SpecFlow.NetCore" Version="1.0.0-rc8" />
</ItemGroup>
Expand All @@ -24,9 +24,9 @@
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>

<Target Name="PrecompileScript" BeforeTargets="BeforeBuild">
<Exec Command="dotnet SpecFlow.NetCore" />
</Target>
<Target Name="PrecompileScript" BeforeTargets="BeforeBuild">
<Exec Command="dotnet SpecFlow.NetCore" />
</Target>

<ItemGroup>
<DotNetCliToolReference Include="SpecFlow.NetCore" Version="1.0.0-rc8" />
Expand Down
4 changes: 2 additions & 2 deletions sample/Sample.Test/Api/GetBlogs/GetBlogsApiTest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace GeekLearning.Test.Integration.Sample.Test.Api.GetBlogs
namespace GeekLearning.Testavior.Sample.Test.Api.GetBlogs
{
using GeekLearning.Test.Integration.Sample.Data;
using GeekLearning.Testavior.Sample.Data;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using System.Collections.Generic;
Expand Down
6 changes: 3 additions & 3 deletions sample/Sample.Test/BaseTestClass.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace GeekLearning.Test.Integration.Sample.Test
namespace GeekLearning.Testavior.Sample.Test
{
using Data;
using Environment;
using GeekLearning.Testavior.Environment;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using System.IO;
Expand All @@ -11,7 +11,7 @@ public abstract class BaseTestClass
{
protected TestEnvironment<Startup, TestStartupConfigurationService<BloggingContext>> TestEnvironment { get; } =
new TestEnvironment<Startup, TestStartupConfigurationService<BloggingContext>>(
Path.Combine(System.AppContext.BaseDirectory, @"..\..\..\..\..\Sample.Web"));
Path.Combine(System.AppContext.BaseDirectory, @"..\..\..\..\Sample.Web"));

protected void CreateBlogs()
{
Expand Down
2 changes: 1 addition & 1 deletion sample/Sample.Test/Mvc/CreateBlog/CreateBlogMvcTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace GeekLearning.Test.Integration.Sample.Test.Mvc.CreateBlog
namespace GeekLearning.Testavior.Sample.Test.Mvc.CreateBlog
{
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand Down
7 changes: 4 additions & 3 deletions sample/Sample.Test/Mvc/GetBlogs/GetBlogsMvcTest.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
namespace GeekLearning.Test.Integration.Sample.Test.Mvc.GetBlogs
namespace GeekLearning.Testavior.Sample.Test.Mvc.GetBlogs
{
using GeekLearning.Test.Integration.Mvc;
using GeekLearning.Test.Integration.Sample.Data;
using GeekLearning.Testavior;
using GeekLearning.Testavior.Mvc;
using GeekLearning.Testavior.Sample.Data;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
Expand Down
Loading

0 comments on commit 559a0e3

Please sign in to comment.