Every software that we make depends on others. For Stankins , as a general ETL data, it is more important to be tested with real data providers.For example, we may want to take data from Sql Server and send to Cachet . How can we have a SqlServer and a Cachet up and running easy ? The obvious answer our days is Docker.
Let’s see how a test for SqlServer looks
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | using FluentAssertions;
using Stankins.Alive;
using Stankins.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xbehave;
using Xunit;
namespace StankinsTestXUnit
{
[Trait( "ReceiverSqlServer" , "" )]
[Trait( "ExternalDependency" , "SqlServer" )]
public class TestReceiverSqlServer
{
[Scenario]
[Example( "Server=(local);Database=master;User Id=SA;Password = <YourStrong!Passw0rd>;" )]
public void TestReceiverDBServer( string connectionString)
{
IReceive status = null ;
IDataToSent data = null ;
$ "Assume Sql Server instance {connectionString} exists , if not see docker folder" .w(() => {
});
$ "When I create the ReceiverDBServer " .w(() => status = new ReceiverDBSqlServer(connectionString));
$ "and receive data" .w( async () =>
{
data = await status.TransformData( null );
});
$ "the data should have a table" .w(() =>
{
data.DataToBeSentFurther.Count.Should().Be(1);
});
$ "and the result should be true" .w(() =>
{
data.DataToBeSentFurther[0].Rows[0][ "IsSuccess" ].Should().Be( true );
});
}
}
}
|
and for cachet :
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | using FluentAssertions;
using Stankins.FileOps;
using Stankins.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Stankins.Rest;
using Xbehave;
using Xunit;
using static System.Environment;
using Stankins.Trello;
using Stankins.Cachet;
namespace StankinsTestXUnit
{
[Trait( "Cachet" , "" )]
[Trait( "ExternalDependency" , "Cachet" )]
public class TestSenderCachet
{
[Scenario]
[Example( "Assets/JSON/CachetV1Simple.txt" , 3)]
public void TestSimpleJSON( string fileName, int NumberRows)
{
IReceive receiver = null ;
IDataToSent data= null ;
var nl = Environment.NewLine;
$ "Given the file {fileName}" .w(() =>
{
File.Exists(fileName).Should().BeTrue();
});
$ "When I create the {nameof(ReceiveRest)} for the {fileName}" .w(() => receiver = new ReceiveRestFromFile(fileName));
$ "And I read the data" .w( async () =>data= await receiver.TransformData( null ));
$ "Then should be a data" .w(() => data.Should().NotBeNull());
$ "With a table" .w(() =>
{
data.DataToBeSentFurther.Should().NotBeNull();
data.DataToBeSentFurther.Count.Should().Be(1);
});
$ "The number of rows should be {NumberRows}" .w(() => data.DataToBeSentFurther[0].Rows.Count.Should().Be(NumberRows));
$ "and now I transform with {nameof(SenderCachet)}" .w( async ()=>
);
}
}
}
|
( I have use XBehave for extensions)
Nice and easy , right ? Not so!
For up and running SqlServer I have used a docker compose file
version: '3'
services:
db:
image: mcr.microsoft.com/mssql/server
ports:
- "1433:1433"
environment:
SA_PASSWORD: "<YourStrong!Passw0rd>"
ACCEPT_EULA: "Y"
healthcheck:
test: sqlcmd -S (local) -U SA -P '<YourStrong!Passw0rd>' -Q 'select 1'
and in AzureDevOps yaml start the containers, run the tests, collect the code coverage, stop the containers
docker-compose -f stankinsv2/solution/StankinsV2/StankinsTestXUnit/Docker/docker-sqlserver-instance-linux.yaml up -d
echo 'start regular test'
dotnet build -c $(buildConfiguration) stankinsv2/solution/StankinsV2/StankinsV2.sln
dotnet test stankinsv2/solution/StankinsV2/StankinsTestXUnit/StankinsTestXUnit.csproj --logger trx --logger "console;verbosity=normal" --collect "Code coverage"
echo 'coverlet'
coverlet stankinsv2/solution/StankinsV2/StankinsTestXUnit/bin/$(buildConfiguration)/netcoreapp2.2/StankinsTestXUnit.dll --target "dotnet" --targetargs "test stankinsv2/solution/StankinsV2/StankinsTestXUnit/StankinsTestXUnit.csproj --configuration $(buildConfiguration) --no-build" --format opencover --exclude "[xunit*]*"
echo 'compose down'
docker-compose -f stankinsv2/solution/StankinsV2/StankinsTestXUnit/Docker/docker-sqlserver-instance-linux.yaml down
Easy, right ? That’s because SqlServer is well behaved and has a fully functional image on Docker
That is not so easy with Cachet . Cachet requires configuration – and more, after configuration, it generates a random token for write data ( http://localhost:8000","5DiHQgKbsJqck4TWhMVO ) .
So it will be a task for docker to export the container and import again - easy stuff, right ? Again, not.
So I start a small docker container with
docker run -p 8000:8000 –name myCachetContainer -e APP_KEY=base64:ybug5it9Koxwhfi5a6CORbWdpjVqXxkz/Tyj4K45GKc= -e DEBUG=false -e DB_DRIVER=sqlite cachethq/docker
and then browsing to http://localhost:8000 I have configured and grab the token
Now it is time to export :
docker export myCachetContainer -o cachet.tar
And to import as an image
docker import cachet.tar mycac
And to run the image again
docker run -p 8000:8000 -e APP_KEY=base64:ybug5it9Koxwhfi5a6CORbWdpjVqXxkz/Tyj4K45GKc= -e DEBUG=false -e DB_DRIVER=sqlite cachethq/docker
And the image stopped! After many tries and docker inspect the initial image , I have resulted to
docker run -it -p 8000:8000 -e APP_KEY=base64:ybug5it9Koxwhfi5a6CORbWdpjVqXxkz/Tyj4K45GKc= -e DEBUG=false -e DB_DRIVER=sqlite --workdir /var/www/html --user 1001:1001 mycac "/sbin/entrypoint.sh"
So the workdir, user, and the entry point are not copied into the image and you should do youurself.
The final preparing for CI with Docker for Cachet ? I have docker push myimage to Docker Hub , and I will run it from docker compose.
So now my docker compose with sql server and cachet looks this way
version: '3'
services:
db:
image: mcr.microsoft.com/mssql/server
ports:
- "1433:1433"
environment:
SA_PASSWORD: "<YourStrong!Passw0rd>"
ACCEPT_EULA: "Y"
healthcheck:
test: sqlcmd -S (local) -U SA -P '<YourStrong!Passw0rd>' -Q 'select 1'
cachet:
image: ignatandrei/ci_cachet
ports:
- "8000:8000"
environment:
APP_KEY: "base64:ybug5it9Koxwhfi5a6CORbWdpjVqXxkz/Tyj4K45GKc="
DEBUG: "false"
DB_DRIVER: "sqlite"
user: "1001"
working_dir: "/var/www/html"
entrypoint: "/sbin/entrypoint.sh"
And I have a nice C# integration tests with Azure Devops, Docker, Sql Server and Cachet ! You can see the code coverage report at https://codecov.io/gh/ignatandrei/stankins/src/master/stankinsv2/solution/StankinsV2/Stankins.Cachet/SenderCachet.cs