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
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 :
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 ()=>
data=await new SenderCachet("http://localhost:8000","5DiHQgKbsJqck4TWhMVO").TransformData(data)
);
}
}
}
( 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