Totem is a tool for testing the contract (message format) used by both producers and consumers; primarily for messaging used in distributed systems (like microservices). Once deployed, the Totem API will allow for automated message testing for both providers and consumers, and a GUI for manual testing by developers. Users can also view existing contracts through the GUI.
The UI allows:
Example of running Totem locally, and hitting the API with Postman:
POST to https://localhost:5001/api/TestMessage/
(Totem API URL)
Body: (raw), type JSON
{
"ContractId": "8f466572-2dd4-47fb-4417-08d6e901c90a",
"Message": {"ID": "00000000-0000-0000-0000-00000000000", "Timestamp": "5/6/2019"}
}
Example valid Contract String, using the OpenAPI schema format:
{
"Contract":{
"type":"object",
"properties":{
"Id":{
"$ref": "#/Guid"
},
"Timestamp":{
"type":"string",
"format":"date-time"
}
}
},
"Guid": {
"type": "string",
"pattern": "^(([0-9a-f]){8}-([0-9a-f]){4}-([0-9a-f]){4}-([0-9a-f]){4}-([0-9a-f]){12})$"
}
}
To test the validity of messages as a producer/consumer through the Totem API, we will need to add tests to a new/existing project, while specifying the contract ID and sample message.
{
"Contract": {
"type": "object",
"properties": {
"OrderId": {
"$ref": "#/Guid"
},
"ItemName": {
"type": "string"
},
"Total" : {
"type": "integer"
},
"Timestamp": {
"type": "string",
"format": "date-time",
"example": "2019-01-01T18:14:29Z"
}
}
},
"Guid": {
"type": "string",
"pattern": "^(([0-9a-f]){8}-([0-9a-f]){4}-([0-9a-f]){4}-([0-9a-f]){4}-([0-9a-f]){12})$",
"minLength": 36,
"maxLength": 36,
"example": "01234567-abcd-0123-abcd-0123456789ab"
}
}
For the new contract that was just created, retrieve the "Contract ID" which will be used to denote which template our message needs to be validated against.
Now we need to add tests to ensure the message is valid, using either a new/existing application.
The tests will make a call to the Totem API with the contract ID and sample message.
Below is an example snippet for testing the validity and success of a message schema:
var anonymousOrderMessage = new
{
ContractId = Guid.Parse("replace-with-actual-guid-id-from-above"),
Message = new
{
OrderId = placeOrder.OrderId,
ItemName = placeOrder.ItemName,
Total = placeOrder.Total,
Timestamp = DateTime.Now
}
};
var stringContent = new StringContent(JsonConvert.SerializeObject(anonymousOrderMessage), Encoding.UTF8, "application/json");
var client = new HttpClient();
var response = await client.PostAsync("https://localhost:5001/api/TestMessage", stringContent);
response.EnsureSuccessStatusCode();
https://localhost:5001/api/TestMessage/
To test that a message is invalid, you could simply use the same message above, but this time, include another field that isn't specified in the contract to see the results of the call, like so:
var invalidAnonymousOrderMessage = new
{
ContractId = Guid.Parse("replace-with-actual-guid-id-from-above"),
Message = new
{
OrderId = placeOrder.OrderId,
ItemName = placeOrder.ItemName,
Total = placeOrder.Total,
Timestamp = DateTime.Now,
NonExistentField = "This should not validate"
}
};
...
...
The above were just two examples of testing a valid and invalid message thru the Totem API. Of course, feel free to test against the API how you see fit, but hopefully the examples above help get you started.
If there was a need to include a new field in a contract, edit the type for an existing field, or delete a field on the contract schema, we would do so by updating the contract in the Totem UI. Then, re-run the tests to ensure their validity.
The ideal scenario for using Totem would be to add these tests into your build, so that before a publish or deploy, you are aware if your code is out of compliance with the expected contract, giving you a heads-up before potentially pushing breaking changes.
double.Parse
and float.Parse
methods behave differently as mentioned in this Coreclr issue thread.float.IsFinite
and double.IsFinite
. We don't anticipate issues with this. If you get any, please create an issue..\build
to run the build script and initialize the DBnpm i
to install node modulesMost of the application's UI is built in C#, but components that require special interaction (like the contract string editor) are built in JavaScript using Vue.
Dev environment recommendations
"editor.renderWhitespace": "all",
"editor.tabSize": 2,
"editor.formatOnSave": true,
"eslint.alwaysShowStatus": true,
"eslint.validate": [
{ "language": "vue", "autoFix": false },
{ "language": "html", "autoFix": false },
{ "language": "javascript", "autoFix": false }
]
Running locally
Debugging the Totem application (either through Visual Studio or from the command line, using dotnet run
will automatically build and run the webpack dev server, transpiling and generating the javascript files needed by the front end. If you use the command line to debug, it will not automatically launch a browser window for you, but you can find the port it is running on in the console output:
Now listening on: https://localhost:5001
.
Tests
To run javascript logic tests, on the command line from the src/Totem folder, run npm run test
.
To run end-to-end tests using TestCafe, on the command line from the src/Totem folder, run npm run e2e
.
master
.develop
, and name your branch starting with the issue number. Ex: 10_Feature_description
Designed and built by Headspring