diff --git a/res/MessageBus.drawio b/res/MessageBus.drawio new file mode 100644 index 0000000..e4da87a --- /dev/null +++ b/res/MessageBus.drawio @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/MessageBus.png b/res/MessageBus.png new file mode 100644 index 0000000..1f0d121 Binary files /dev/null and b/res/MessageBus.png differ diff --git a/res/MessageBus.txt b/res/MessageBus.txt new file mode 100644 index 0000000..d530433 --- /dev/null +++ b/res/MessageBus.txt @@ -0,0 +1,66 @@ +[xUnit.net 00:00:02.64] KiBoards.Tests: MessageBus: Xunit.Sdk.TestMethodStarting + +[xUnit.net 00:00:02.67] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseStarting +[xUnit.net 00:00:02.67] KiBoards.Tests: MessageBus: Xunit.Sdk.TestStarting +[xUnit.net 00:00:02.67] KiBoards.Tests: MessageBus: Xunit.Sdk.TestClassConstructionStarting +[xUnit.net 00:00:02.67] KiBoards.Tests: MessageBus: Xunit.Sdk.TestClassConstructionFinished +[xUnit.net 00:00:02.68] KiBoards.Tests: MessageBus: Xunit.Sdk.TestPassed +[xUnit.net 00:00:02.68] KiBoards.Tests: MessageBus: Xunit.Sdk.TestFinished +[xUnit.net 00:00:02.68] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseFinished + +[xUnit.net 00:00:02.71] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseStarting +[xUnit.net 00:00:02.71] KiBoards.Tests: MessageBus: Xunit.Sdk.TestStarting +[xUnit.net 00:00:02.71] KiBoards.Tests: MessageBus: Xunit.Sdk.TestClassConstructionStarting +[xUnit.net 00:00:02.71] KiBoards.Tests: MessageBus: Xunit.Sdk.TestClassConstructionFinished +[xUnit.net 00:00:02.72] KiBoards.Tests: MessageBus: Xunit.Sdk.TestFailed +[xUnit.net 00:00:02.72] KiBoards.Tests: MessageBus: Xunit.Sdk.TestFinished +[xUnit.net 00:00:02.72] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseFinished + +[xUnit.net 00:00:02.73] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseStarting +[xUnit.net 00:00:02.73] KiBoards.Tests: MessageBus: Xunit.Sdk.TestStarting +[xUnit.net 00:00:02.73] KiBoards.Tests: MessageBus: Xunit.Sdk.TestClassConstructionStarting +[xUnit.net 00:00:02.73] KiBoards.Tests: MessageBus: Xunit.Sdk.TestClassConstructionFinished + +[xUnit.net 00:00:02.73] KiBoards.Tests: MessageBus: Xunit.Sdk.TestPassed +[xUnit.net 00:00:02.73] KiBoards.Tests: MessageBus: Xunit.Sdk.TestFinished + +[xUnit.net 00:00:02.73] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseFinished + +[xUnit.net 00:00:02.74] KiBoards.Tests: MessageBus: Xunit.Sdk.TestMethodFinished + + +[xUnit.net 00:00:02.74] KiBoards.Tests: MessageBus: Xunit.Sdk.TestMethodStarting +[xUnit.net 00:00:02.75] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseStarting +[xUnit.net 00:00:02.75] KiBoards.Tests: MessageBus: Xunit.Sdk.TestStarting +[xUnit.net 00:00:02.75] KiBoards.Tests: MessageBus: Xunit.Sdk.TestClassConstructionStarting +[xUnit.net 00:00:02.75] KiBoards.Tests: MessageBus: Xunit.Sdk.TestClassConstructionFinished + +[xUnit.net 00:00:02.75] KiBoards.Tests: MessageBus: Xunit.Sdk.TestPassed +[xUnit.net 00:00:02.75] KiBoards.Tests: MessageBus: Xunit.Sdk.TestFinished + +[xUnit.net 00:00:02.75] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseFinished +[xUnit.net 00:00:02.75] KiBoards.Tests: MessageBus: Xunit.Sdk.TestMethodFinished + +[xUnit.net 00:00:02.75] KiBoards.Tests: MessageBus: Xunit.Sdk.TestMethodStarting +[xUnit.net 00:00:02.76] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseStarting +[xUnit.net 00:00:02.76] KiBoards.Tests: MessageBus: Xunit.Sdk.TestStarting +[xUnit.net 00:00:02.76] KiBoards.Tests: MessageBus: Xunit.Sdk.TestClassConstructionStarting +[xUnit.net 00:00:02.76] KiBoards.Tests: MessageBus: Xunit.Sdk.TestClassConstructionFinished + +[xUnit.net 00:00:02.76] KiBoards.Tests: MessageBus: Xunit.Sdk.TestFailed +[xUnit.net 00:00:02.76] KiBoards.Tests: MessageBus: Xunit.Sdk.TestFinished + +[xUnit.net 00:00:02.76] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseFinished +[xUnit.net 00:00:02.77] KiBoards.Tests: MessageBus: Xunit.Sdk.TestMethodFinished + +[xUnit.net 00:00:02.77] KiBoards.Tests: MessageBus: Xunit.Sdk.TestMethodStarting +[xUnit.net 00:00:02.77] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseStarting +[xUnit.net 00:00:02.77] KiBoards.Tests: MessageBus: Xunit.Sdk.TestStarting + +[xUnit.net 00:00:02.77] KiBoards.Tests: MessageBus: Xunit.Sdk.TestSkipped +[xUnit.net 00:00:02.77] KiBoards.Tests: MessageBus: Xunit.Sdk.TestFinished + +[xUnit.net 00:00:02.77] KiBoards.Tests: MessageBus: Xunit.Sdk.TestCaseFinished +[xUnit.net 00:00:02.78] KiBoards.Tests: MessageBus: Xunit.Sdk.TestMethodFinished + +Failed! - Failed: 2, Passed: 3, Skipped: 1, Total: 6, Duration: 85 ms - KiBoards.Tests.dll (net7.0) diff --git a/res/TestCaseStatus.ndjson b/res/TestCaseStatus.ndjson new file mode 100644 index 0000000..87d6a87 --- /dev/null +++ b/res/TestCaseStatus.ndjson @@ -0,0 +1,5 @@ +{"attributes":{"fieldAttrs":"{\"displayName\":{\"count\":2},\"state\":{\"count\":1},\"uniqueId\":{\"customLabel\":\"Id\",\"count\":1},\"status\":{\"customLabel\":\"Status\",\"count\":1},\"summary.time\":{\"count\":1}}","fieldFormatMap":"{\"status\":{\"id\":\"color\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:5601\",\"pathname\":\"/app/home\",\"basePath\":\"\"},\"fieldType\":\"string\",\"colors\":[{\"range\":\"-Infinity:Infinity\",\"regex\":\"Success\",\"text\":\"#459b83\",\"background\":\"#ffffff\"},{\"range\":\"-Infinity:Infinity\",\"regex\":\"Failure\",\"text\":\"#E7664C\",\"background\":\"#ffffff\"},{\"range\":\"-Infinity:Infinity\",\"regex\":\"Skipped\",\"text\":\"#D6BF57\",\"background\":\"#ffffff\"}]}}}","fields":"[]","name":"Test Case Status View","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"","title":"kiboards-testcase-status-*","typeMeta":"{}"},"coreMigrationVersion":"8.8.0","created_at":"2023-09-21T21:40:51.247Z","id":"641b8927-249c-4669-9dea-a6bf989c8556","managed":false,"references":[],"type":"index-pattern","typeMigrationVersion":"8.0.0","updated_at":"2023-09-21T21:40:51.247Z","version":"WzUsMl0="} +{"attributes":{"columns":["uniqueId","status","displayName"],"description":"","grid":{"columns":{"status":{"width":86},"uniqueId":{"width":313}}},"hideChart":false,"isTextBasedQuery":false,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"rowHeight":-1,"sort":[],"timeRestore":false,"title":"Test Case Status Search","usesAdHocDataView":false,"viewMode":"documents"},"coreMigrationVersion":"8.8.0","created_at":"2023-09-21T21:40:51.247Z","id":"fd2b4c00-34a7-11ee-8f8e-e312ee55ca24","managed":false,"references":[{"id":"641b8927-249c-4669-9dea-a6bf989c8556","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"search","typeMigrationVersion":"8.0.0","updated_at":"2023-09-21T21:40:51.247Z","version":"WzYsMl0="} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.8.2\",\"type\":\"search\",\"gridData\":{\"x\":0,\"y\":0,\"w\":48,\"h\":29,\"i\":\"f0134ca4-cbcd-483e-9107-6e93fba7de2f\"},\"panelIndex\":\"f0134ca4-cbcd-483e-9107-6e93fba7de2f\",\"embeddableConfig\":{\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Details\",\"panelRefName\":\"panel_f0134ca4-cbcd-483e-9107-6e93fba7de2f\"}]","timeRestore":false,"title":"Test Case Details","version":1},"coreMigrationVersion":"8.8.0","created_at":"2023-09-21T21:40:51.247Z","id":"00115f80-34a9-11ee-8f8e-e312ee55ca24","managed":false,"references":[{"id":"fd2b4c00-34a7-11ee-8f8e-e312ee55ca24","name":"f0134ca4-cbcd-483e-9107-6e93fba7de2f:panel_f0134ca4-cbcd-483e-9107-6e93fba7de2f","type":"search"}],"type":"dashboard","typeMigrationVersion":"8.9.0","updated_at":"2023-09-21T21:40:51.247Z","version":"WzcsMl0="} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.9.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":8,\"h\":6,\"i\":\"10c370c6-5da2-4507-ad86-af1119649a69\"},\"panelIndex\":\"10c370c6-5da2-4507-ad86-af1119649a69\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"description\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"id\":\"641b8927-249c-4669-9dea-a6bf989c8556\",\"name\":\"indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"layerId\":\"be565c3a-655e-4ed9-97f2-7b4435618318\",\"accessor\":\"c442ed00-679d-451f-b0b1-da6b8674d186\",\"layerType\":\"data\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":0,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#afb8c6\",\"stop\":1},{\"color\":\"#343741\",\"stop\":20}],\"continuity\":\"above\",\"maxSteps\":5,\"colorStops\":[{\"color\":\"#afb8c6\",\"stop\":0},{\"color\":\"#343741\",\"stop\":1}]}},\"textAlign\":\"center\",\"size\":\"l\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"be565c3a-655e-4ed9-97f2-7b4435618318\":{\"columns\":{\"c442ed00-679d-451f-b0b1-da6b8674d186\":{\"label\":\"Total\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":false,\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0,\"suffix\":\"\"}}},\"customLabel\":true}},\"columnOrder\":[\"c442ed00-679d-451f-b0b1-da6b8674d186\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":true,\"description\":\"Currently running test cases\",\"enhancements\":{}},\"title\":\"\"},{\"version\":\"8.9.2\",\"type\":\"lens\",\"gridData\":{\"x\":8,\"y\":0,\"w\":8,\"h\":6,\"i\":\"0b4751ed-1f30-4405-9801-1ccf24a0b956\"},\"panelIndex\":\"0b4751ed-1f30-4405-9801-1ccf24a0b956\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"description\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"id\":\"641b8927-249c-4669-9dea-a6bf989c8556\",\"name\":\"indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"layerId\":\"be565c3a-655e-4ed9-97f2-7b4435618318\",\"accessor\":\"c442ed00-679d-451f-b0b1-da6b8674d186\",\"layerType\":\"data\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":0,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#afb8c6\",\"stop\":20},{\"color\":\"#6d7482\",\"stop\":50},{\"color\":\"#343741\",\"stop\":100}],\"continuity\":\"above\",\"maxSteps\":5,\"colorStops\":[{\"color\":\"#afb8c6\",\"stop\":0},{\"color\":\"#6d7482\",\"stop\":20},{\"color\":\"#343741\",\"stop\":50}]}},\"titlePosition\":\"top\",\"size\":\"l\",\"textAlign\":\"center\"},\"query\":{\"query\":\"status.keyword : \\\"Discovered\\\" \",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"be565c3a-655e-4ed9-97f2-7b4435618318\":{\"columns\":{\"c442ed00-679d-451f-b0b1-da6b8674d186\":{\"label\":\"Discovered\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":false,\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0,\"suffix\":\"\"}}},\"customLabel\":true}},\"columnOrder\":[\"c442ed00-679d-451f-b0b1-da6b8674d186\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":true,\"description\":\"Currently running test cases\",\"enhancements\":{}},\"title\":\"\"},{\"version\":\"8.9.2\",\"type\":\"lens\",\"gridData\":{\"x\":16,\"y\":0,\"w\":8,\"h\":6,\"i\":\"408ce981-f6e4-48c8-85c0-78231aa10b65\"},\"panelIndex\":\"408ce981-f6e4-48c8-85c0-78231aa10b65\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"description\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"id\":\"641b8927-249c-4669-9dea-a6bf989c8556\",\"name\":\"indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"layerId\":\"be565c3a-655e-4ed9-97f2-7b4435618318\",\"accessor\":\"c442ed00-679d-451f-b0b1-da6b8674d186\",\"layerType\":\"data\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":0,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#afb8c6\",\"stop\":20},{\"color\":\"#6d7482\",\"stop\":50},{\"color\":\"#343741\",\"stop\":100}],\"continuity\":\"above\",\"maxSteps\":5,\"colorStops\":[{\"color\":\"#afb8c6\",\"stop\":0},{\"color\":\"#6d7482\",\"stop\":20},{\"color\":\"#343741\",\"stop\":50}]}},\"textAlign\":\"center\",\"size\":\"l\"},\"query\":{\"query\":\"status.keyword : \\\"Running\\\" \",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"be565c3a-655e-4ed9-97f2-7b4435618318\":{\"columns\":{\"c442ed00-679d-451f-b0b1-da6b8674d186\":{\"label\":\"Running\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":false,\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0,\"suffix\":\"\"}}},\"customLabel\":true}},\"columnOrder\":[\"c442ed00-679d-451f-b0b1-da6b8674d186\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":true,\"description\":\"Currently running test cases\",\"enhancements\":{}},\"title\":\"Running\"},{\"version\":\"8.9.2\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":8,\"h\":6,\"i\":\"ba96163c-6fff-4602-bbe1-bd6e4c1d01b7\"},\"panelIndex\":\"ba96163c-6fff-4602-bbe1-bd6e4c1d01b7\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"description\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"id\":\"641b8927-249c-4669-9dea-a6bf989c8556\",\"name\":\"indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"layerId\":\"be565c3a-655e-4ed9-97f2-7b4435618318\",\"accessor\":\"c442ed00-679d-451f-b0b1-da6b8674d186\",\"layerType\":\"data\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":0,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#00000054\",\"stop\":1},{\"color\":\"#209280\",\"stop\":18}],\"continuity\":\"above\",\"maxSteps\":5,\"colorStops\":[{\"color\":\"#00000054\",\"stop\":0},{\"color\":\"#209280\",\"stop\":1}]}},\"textAlign\":\"center\",\"size\":\"l\"},\"query\":{\"query\":\"status.keyword : \\\"Success\\\" \",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"be565c3a-655e-4ed9-97f2-7b4435618318\":{\"columns\":{\"c442ed00-679d-451f-b0b1-da6b8674d186\":{\"label\":\"Success\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":false,\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0,\"suffix\":\"\"}}},\"customLabel\":true}},\"columnOrder\":[\"c442ed00-679d-451f-b0b1-da6b8674d186\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":true,\"description\":\"Currently running test cases\",\"enhancements\":{}},\"title\":\"\"},{\"version\":\"8.9.2\",\"type\":\"lens\",\"gridData\":{\"x\":32,\"y\":0,\"w\":8,\"h\":6,\"i\":\"446f37b5-2f7f-4814-8d3f-f7b1cae9e007\"},\"panelIndex\":\"446f37b5-2f7f-4814-8d3f-f7b1cae9e007\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"description\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"id\":\"641b8927-249c-4669-9dea-a6bf989c8556\",\"name\":\"indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"layerId\":\"be565c3a-655e-4ed9-97f2-7b4435618318\",\"accessor\":\"c442ed00-679d-451f-b0b1-da6b8674d186\",\"layerType\":\"data\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":0,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#27987e\",\"stop\":1},{\"color\":\"#E7664C\",\"stop\":18}],\"continuity\":\"above\",\"maxSteps\":5,\"colorStops\":[{\"color\":\"#27987e\",\"stop\":0},{\"color\":\"#E7664C\",\"stop\":1}]}},\"textAlign\":\"center\",\"size\":\"l\"},\"query\":{\"query\":\"status.keyword : \\\"Failure\\\" \",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"be565c3a-655e-4ed9-97f2-7b4435618318\":{\"columns\":{\"c442ed00-679d-451f-b0b1-da6b8674d186\":{\"label\":\"Failure\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":false,\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0,\"suffix\":\"\"}}},\"customLabel\":true}},\"columnOrder\":[\"c442ed00-679d-451f-b0b1-da6b8674d186\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":true,\"description\":\"Currently running test cases\",\"enhancements\":{}},\"title\":\"\"},{\"version\":\"8.9.2\",\"type\":\"lens\",\"gridData\":{\"x\":40,\"y\":0,\"w\":8,\"h\":6,\"i\":\"f33640a2-03d3-4cb8-9514-ac7eddb8342c\"},\"panelIndex\":\"f33640a2-03d3-4cb8-9514-ac7eddb8342c\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"description\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"id\":\"641b8927-249c-4669-9dea-a6bf989c8556\",\"name\":\"indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"layerId\":\"be565c3a-655e-4ed9-97f2-7b4435618318\",\"accessor\":\"c442ed00-679d-451f-b0b1-da6b8674d186\",\"layerType\":\"data\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":0,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#0000003b\",\"stop\":1},{\"color\":\"#D6BF57\",\"stop\":100}],\"continuity\":\"above\",\"maxSteps\":5,\"colorStops\":[{\"color\":\"#0000003b\",\"stop\":0},{\"color\":\"#D6BF57\",\"stop\":1}]}},\"textAlign\":\"center\",\"size\":\"l\"},\"query\":{\"query\":\"status.keyword : \\\"Skipped\\\" \",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"be565c3a-655e-4ed9-97f2-7b4435618318\":{\"columns\":{\"c442ed00-679d-451f-b0b1-da6b8674d186\":{\"label\":\"Skipped\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":false,\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0,\"suffix\":\"\"}}},\"customLabel\":true}},\"columnOrder\":[\"c442ed00-679d-451f-b0b1-da6b8674d186\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":true,\"description\":\"Currently running test cases\",\"enhancements\":{}},\"title\":\"\"},{\"version\":\"8.9.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":6,\"w\":16,\"h\":15,\"i\":\"2be22eb0-e753-4d1d-8ec5-bdde80a69fd5\"},\"panelIndex\":\"2be22eb0-e753-4d1d-8ec5-bdde80a69fd5\",\"embeddableConfig\":{\"attributes\":{\"title\":\"Test Cases\",\"description\":\"\",\"visualizationType\":\"lnsPie\",\"type\":\"lens\",\"references\":[{\"id\":\"641b8927-249c-4669-9dea-a6bf989c8556\",\"name\":\"indexpattern-datasource-layer-6f0b74bd-09b6-4d1a-a8b5-92e6cf653216\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"shape\":\"donut\",\"palette\":{\"type\":\"palette\",\"name\":\"positive\"},\"layers\":[{\"layerId\":\"6f0b74bd-09b6-4d1a-a8b5-92e6cf653216\",\"primaryGroups\":[\"6fc4244c-c2d2-4558-8016-cc3d656f4dba\"],\"metrics\":[\"742e3600-35ca-4446-aac6-519f26cb3b13\"],\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"hide\",\"nestedLegend\":false,\"layerType\":\"data\",\"emptySizeRatio\":0.54,\"truncateLegend\":true,\"legendPosition\":\"left\",\"allowMultipleMetrics\":false}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"6f0b74bd-09b6-4d1a-a8b5-92e6cf653216\":{\"columns\":{\"6fc4244c-c2d2-4558-8016-cc3d656f4dba\":{\"label\":\"Top 6 values of status.keyword\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"status.keyword\",\"isBucketed\":true,\"params\":{\"size\":6,\"orderBy\":{\"type\":\"column\",\"columnId\":\"742e3600-35ca-4446-aac6-519f26cb3b13\"},\"orderDirection\":\"asc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}},\"742e3600-35ca-4446-aac6-519f26cb3b13\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"6fc4244c-c2d2-4558-8016-cc3d656f4dba\",\"742e3600-35ca-4446-aac6-519f26cb3b13\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"bf63f130-7338-4092-ba4d-8b2b9a9d478c\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Go to test case details...\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":false,\"openInNewTab\":false}}}]}},\"hidePanelTitles\":true}},{\"version\":\"8.9.2\",\"type\":\"visualization\",\"gridData\":{\"x\":16,\"y\":6,\"w\":16,\"h\":15,\"i\":\"873943d5-ace4-4e99-bbd2-221623eaf293\"},\"panelIndex\":\"873943d5-ace4-4e99-bbd2-221623eaf293\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"\",\"description\":\"\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":26,\"maxFontSize\":72,\"showLabel\":false,\"palette\":{\"type\":\"palette\",\"name\":\"status\"}},\"uiState\":{},\"data\":{\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{\"emptyAsNull\":false},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"status.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":true,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"includeIsRegex\":true,\"excludeIsRegex\":true},\"schema\":\"segment\"}],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}}},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"a3885ac3-b583-429d-bfbd-36aa4b5ac2a3\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Go to Dashboard\",\"config\":{\"useCurrentFilters\":false,\"useCurrentDateRange\":false,\"openInNewTab\":false}}}]}}}},{\"version\":\"8.9.2\",\"type\":\"lens\",\"gridData\":{\"x\":32,\"y\":6,\"w\":16,\"h\":15,\"i\":\"d0939bca-79c1-4c67-bdd6-51c445abcf56\"},\"panelIndex\":\"d0939bca-79c1-4c67-bdd6-51c445abcf56\",\"embeddableConfig\":{\"attributes\":{\"title\":\"Test Cases\",\"description\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"641b8927-249c-4669-9dea-a6bf989c8556\",\"name\":\"indexpattern-datasource-layer-6f0b74bd-09b6-4d1a-a8b5-92e6cf653216\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":false,\"position\":\"bottom\",\"showSingleSeries\":false,\"isInside\":false,\"shouldTruncate\":false},\"valueLabels\":\"show\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":false,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":false,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":false,\"yLeft\":false,\"yRight\":true},\"preferredSeriesType\":\"bar_horizontal_stacked\",\"layers\":[{\"layerId\":\"6f0b74bd-09b6-4d1a-a8b5-92e6cf653216\",\"seriesType\":\"bar_horizontal_stacked\",\"xAccessor\":\"6fc4244c-c2d2-4558-8016-cc3d656f4dba\",\"accessors\":[\"742e3600-35ca-4446-aac6-519f26cb3b13\",\"64851214-2c34-44e3-838b-0af27323929b\",\"56018286-5231-4400-8d02-7653525b322a\",\"ee233af9-d011-4bcd-a19e-275aaf9f36f1\",\"2724574b-d6f9-4f13-8eb0-646a4b863619\"],\"yConfig\":[{\"forAccessor\":\"64851214-2c34-44e3-838b-0af27323929b\",\"color\":\"#54b399\"},{\"forAccessor\":\"742e3600-35ca-4446-aac6-519f26cb3b13\",\"color\":\"#e7664c\"},{\"forAccessor\":\"56018286-5231-4400-8d02-7653525b322a\",\"color\":\"#d6bf57\"},{\"forAccessor\":\"ee233af9-d011-4bcd-a19e-275aaf9f36f1\",\"color\":\"#aaaaaa\",\"axisMode\":\"auto\"},{\"forAccessor\":\"2724574b-d6f9-4f13-8eb0-646a4b863619\",\"color\":\"#cccccc\"}],\"layerType\":\"data\"}],\"yLeftExtent\":{\"mode\":\"full\",\"niceValues\":false}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"6f0b74bd-09b6-4d1a-a8b5-92e6cf653216\":{\"columns\":{\"6fc4244c-c2d2-4558-8016-cc3d656f4dba\":{\"label\":\"Status\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"status.keyword\",\"isBucketed\":true,\"params\":{\"size\":6,\"orderBy\":{\"type\":\"custom\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"orderAgg\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}},\"secondaryFields\":[]},\"customLabel\":true},\"742e3600-35ca-4446-aac6-519f26cb3b13\":{\"label\":\"Failure\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"status.keyword\",\"params\":{\"emptyAsNull\":false,\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0}}},\"customLabel\":true,\"filter\":{\"query\":\"status.keyword : \\\"Failure\\\" \",\"language\":\"kuery\"}},\"64851214-2c34-44e3-838b-0af27323929b\":{\"label\":\"Success\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"status.keyword\",\"filter\":{\"query\":\"status.keyword : \\\"Success\\\" \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"56018286-5231-4400-8d02-7653525b322a\":{\"label\":\"Skipped\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"status.keyword\",\"filter\":{\"query\":\"status.keyword : \\\"Skipped\\\"\",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"ee233af9-d011-4bcd-a19e-275aaf9f36f1\":{\"label\":\"Running\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"status.keyword\",\"filter\":{\"query\":\"status.keyword : \\\"Running\\\"\",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"2724574b-d6f9-4f13-8eb0-646a4b863619\":{\"label\":\"Discovered\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"status.keyword\",\"filter\":{\"query\":\"status.keyword : \\\"Discovered\\\" \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":false},\"customLabel\":true}},\"columnOrder\":[\"6fc4244c-c2d2-4558-8016-cc3d656f4dba\",\"742e3600-35ca-4446-aac6-519f26cb3b13\",\"64851214-2c34-44e3-838b-0af27323929b\",\"56018286-5231-4400-8d02-7653525b322a\",\"ee233af9-d011-4bcd-a19e-275aaf9f36f1\",\"2724574b-d6f9-4f13-8eb0-646a4b863619\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"2b53c149-d516-401e-a487-c6efda1ade02\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\",\"name\":\"Go to test case details...\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":false,\"openInNewTab\":false}}}]}},\"hidePanelTitles\":true},\"title\":\"\"}]","timeRestore":false,"title":"Test Case Status","version":1},"coreMigrationVersion":"8.8.0","created_at":"2023-09-21T22:06:31.557Z","id":"1b934de0-34a9-11ee-8f8e-e312ee55ca24","managed":false,"references":[{"id":"641b8927-249c-4669-9dea-a6bf989c8556","name":"10c370c6-5da2-4507-ad86-af1119649a69:indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318","type":"index-pattern"},{"id":"641b8927-249c-4669-9dea-a6bf989c8556","name":"0b4751ed-1f30-4405-9801-1ccf24a0b956:indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318","type":"index-pattern"},{"id":"641b8927-249c-4669-9dea-a6bf989c8556","name":"408ce981-f6e4-48c8-85c0-78231aa10b65:indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318","type":"index-pattern"},{"id":"641b8927-249c-4669-9dea-a6bf989c8556","name":"ba96163c-6fff-4602-bbe1-bd6e4c1d01b7:indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318","type":"index-pattern"},{"id":"641b8927-249c-4669-9dea-a6bf989c8556","name":"446f37b5-2f7f-4814-8d3f-f7b1cae9e007:indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318","type":"index-pattern"},{"id":"641b8927-249c-4669-9dea-a6bf989c8556","name":"f33640a2-03d3-4cb8-9514-ac7eddb8342c:indexpattern-datasource-layer-be565c3a-655e-4ed9-97f2-7b4435618318","type":"index-pattern"},{"id":"641b8927-249c-4669-9dea-a6bf989c8556","name":"2be22eb0-e753-4d1d-8ec5-bdde80a69fd5:indexpattern-datasource-layer-6f0b74bd-09b6-4d1a-a8b5-92e6cf653216","type":"index-pattern"},{"id":"00115f80-34a9-11ee-8f8e-e312ee55ca24","name":"2be22eb0-e753-4d1d-8ec5-bdde80a69fd5:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:bf63f130-7338-4092-ba4d-8b2b9a9d478c:dashboardId","type":"dashboard"},{"id":"641b8927-249c-4669-9dea-a6bf989c8556","name":"873943d5-ace4-4e99-bbd2-221623eaf293:kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"00115f80-34a9-11ee-8f8e-e312ee55ca24","name":"873943d5-ace4-4e99-bbd2-221623eaf293:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:a3885ac3-b583-429d-bfbd-36aa4b5ac2a3:dashboardId","type":"dashboard"},{"id":"641b8927-249c-4669-9dea-a6bf989c8556","name":"d0939bca-79c1-4c67-bdd6-51c445abcf56:indexpattern-datasource-layer-6f0b74bd-09b6-4d1a-a8b5-92e6cf653216","type":"index-pattern"},{"id":"00115f80-34a9-11ee-8f8e-e312ee55ca24","name":"d0939bca-79c1-4c67-bdd6-51c445abcf56:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:2b53c149-d516-401e-a487-c6efda1ade02:dashboardId","type":"dashboard"}],"type":"dashboard","typeMigrationVersion":"8.9.0","updated_at":"2023-09-21T22:06:31.557Z","version":"WzE2OSwyXQ=="} +{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":4,"missingRefCount":0,"missingReferences":[]} \ No newline at end of file diff --git a/src/KiBoards.Tests/KiBoards.Tests.csproj b/src/KiBoards.Tests/KiBoards.Tests.csproj new file mode 100644 index 0000000..ae75601 --- /dev/null +++ b/src/KiBoards.Tests/KiBoards.Tests.csproj @@ -0,0 +1,31 @@ + + + + net7.0 + enable + enable + en + ..\..\bin + false + true + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/src/KiBoards.Tests/UnitTest1.cs b/src/KiBoards.Tests/UnitTest1.cs new file mode 100644 index 0000000..8ffea7b --- /dev/null +++ b/src/KiBoards.Tests/UnitTest1.cs @@ -0,0 +1,52 @@ +using Xunit.Abstractions; +using Xunit.Sdk; + +[assembly: TestFramework("KiBoards.TestFramework", "KiBoards")] + +namespace KiBoards.Tests +{ + + public class UnitTest1 : IClassFixture + { + readonly TestContextFixture _testContextFixture; + readonly ITestOutputHelper _testOutputHelper; + + public UnitTest1(TestContextFixture testContextFixture, ITestOutputHelper testOutputHelper) + { + _testContextFixture = testContextFixture; + _testOutputHelper = testOutputHelper; + + _testContextFixture.SetContext(new { Version = "Context via Fixture", Hello = "World", Input = 1 }); + } + + [Fact] + public void Test1() + { + + var testCase = _testOutputHelper.GetTestCase(); + + _testContextFixture.SetContext(new { Version = "12345", TestCase = testCase }) ; + Thread.Sleep(1000); + } + + [Fact] + public void Test2() + { + Assert.Equal(1, 2); + } + + + [Fact] + public void Test3() + { + throw new NotImplementedException(); + } + + [Fact(Skip = "Not required.")] + public void Test4() + { + + } + + } +} \ No newline at end of file diff --git a/src/KiBoards.Tests/UnitTest2.cs b/src/KiBoards.Tests/UnitTest2.cs new file mode 100644 index 0000000..19ea6ec --- /dev/null +++ b/src/KiBoards.Tests/UnitTest2.cs @@ -0,0 +1,53 @@ + +using Microsoft.VisualStudio.TestPlatform.Utilities; +using System.Reflection; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace KiBoards.Tests +{ + + public class UnitTest2 : IClassFixture + { + + public UnitTest2(TestContextFixture testContextFixture, ITestOutputHelper outputHelper) + { + // This is how to get messageBus + + testContextFixture.SetContext(new { Version = "1234" }); + + outputHelper.WriteLine("HELLO WORLD MESSAGE BUS"); + } + + [Fact(Timeout = 1000)] + public void Test5() + { + Thread.Sleep(5000); + + + } + + [Theory] + [InlineData(1, 2)] + [InlineData(2, 2)] + [InlineData(3, 3)] + public void Test6(int a, int b) + { + Assert.Equal(a, b); + } + + + [Fact] + public void Test7() + { + throw new NotImplementedException(); + } + + [Fact(Skip = "Not required.")] + public void Test8() + { + + } + + } +} \ No newline at end of file diff --git a/src/KiBoards.Tests/UnitTest3.cs b/src/KiBoards.Tests/UnitTest3.cs new file mode 100644 index 0000000..9918374 --- /dev/null +++ b/src/KiBoards.Tests/UnitTest3.cs @@ -0,0 +1,49 @@ +using Xunit.Abstractions; + +namespace KiBoards.Tests +{ + + public class UnitTest3 : IClassFixture + { + + public UnitTest3(TestContextFixture testContextFixture, ITestOutputHelper outputHelper) + { + // This is how to get messageBus + + testContextFixture.SetContext(new { Version = "1234" }); + + outputHelper.WriteLine("HELLO WORLD MESSAGE BUS"); + } + + [Fact(Timeout = 1000)] + public void Test5() + { + Thread.Sleep(5000); + + + } + + [Theory] + [InlineData(1, 2)] + [InlineData(2, 2)] + [InlineData(3, 3)] + public void Test6(int a, int b) + { + Assert.Equal(a, b); + } + + + [Fact] + public void Test7() + { + throw new NotImplementedException(); + } + + [Fact(Skip = "Not required.")] + public void Test8() + { + + } + + } +} \ No newline at end of file diff --git a/src/KiBoards.Tests/Usings.cs b/src/KiBoards.Tests/Usings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/src/KiBoards.Tests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/src/KiBoards.sln b/src/KiBoards.sln index 43d734a..dbc6024 100644 --- a/src/KiBoards.sln +++ b/src/KiBoards.sln @@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.33516.290 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FDCEF06B-A89A-43CC-B505-4608DF29BBF7}") = "KiBoards", "KiBoards\KiBoards.csproj", "{5DC70E65-1093-4D72-9129-F0FFE3AF5151}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KiBoards", "KiBoards\KiBoards.csproj", "{644D75DA-7457-4DC2-AD9B-2376A7C20BC1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KiBoards.Tests", "KiBoards.Tests\KiBoards.Tests.csproj", "{BD23E63C-CC78-4714-A319-E492CC90178A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -11,15 +13,19 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5DC70E65-1093-4D72-9129-F0FFE3AF5151}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5DC70E65-1093-4D72-9129-F0FFE3AF5151}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5DC70E65-1093-4D72-9129-F0FFE3AF5151}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5DC70E65-1093-4D72-9129-F0FFE3AF5151}.Release|Any CPU.Build.0 = Release|Any CPU + {644D75DA-7457-4DC2-AD9B-2376A7C20BC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {644D75DA-7457-4DC2-AD9B-2376A7C20BC1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {644D75DA-7457-4DC2-AD9B-2376A7C20BC1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {644D75DA-7457-4DC2-AD9B-2376A7C20BC1}.Release|Any CPU.Build.0 = Release|Any CPU + {BD23E63C-CC78-4714-A319-E492CC90178A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD23E63C-CC78-4714-A319-E492CC90178A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD23E63C-CC78-4714-A319-E492CC90178A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD23E63C-CC78-4714-A319-E492CC90178A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {58F0F7CE-57BF-43A9-8390-A15E0C1A9A66} + SolutionGuid = {F7A87B3B-2908-4E34-AC90-13E68B977B90} EndGlobalSection EndGlobal diff --git a/src/KiBoards/Class1.cs b/src/KiBoards/Class1.cs deleted file mode 100644 index 16e7b85..0000000 --- a/src/KiBoards/Class1.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace KiBoards -{ - public class Class1 - { - - } -} \ No newline at end of file diff --git a/src/KiBoards/ITestContextMessage.cs b/src/KiBoards/ITestContextMessage.cs new file mode 100644 index 0000000..0b6df27 --- /dev/null +++ b/src/KiBoards/ITestContextMessage.cs @@ -0,0 +1,9 @@ +using Xunit.Abstractions; + +namespace KiBoards +{ + internal interface ITestContextMessage : IMessageSinkMessage + { + public object Context { get; set; } + } +} diff --git a/src/KiBoards/KiBoards.csproj b/src/KiBoards/KiBoards.csproj index c8246b3..6260214 100644 --- a/src/KiBoards/KiBoards.csproj +++ b/src/KiBoards/KiBoards.csproj @@ -4,7 +4,6 @@ netstandard2.1 ..\..\bin enable - enable 10 @@ -28,15 +27,16 @@ - + - + - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + + diff --git a/src/KiBoards/Models/KiBoardsModelsExtensions.cs b/src/KiBoards/Models/KiBoardsModelsExtensions.cs new file mode 100644 index 0000000..5734afa --- /dev/null +++ b/src/KiBoards/Models/KiBoardsModelsExtensions.cs @@ -0,0 +1,39 @@ +using Nest; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace KiBoards.Models +{ + internal static class KiBoardsModelsExtensions + { + + internal static KiBoardsTestCaseStatusDto ToKiBoardsTestCase(this IXunitTestCase testCase, ITestMethod testMethod, KiBoardsTestCaseStatus status, KiBoardsTestCaseState state, object context = null) => new KiBoardsTestCaseStatusDto() + { + UniqueId = testCase.UniqueID, + DisplayName = testCase.DisplayName, + SkipReason = testCase.SkipReason, + UpdatedOn = DateTime.Now.ToUniversalTime(), + Status = status.ToString(), + State = state.ToString(), + TestMethod = new KiBoardsTestMethodDto() + { + TestClass = new KiBoardsTestClassDto() + { + Name = testMethod?.TestClass.Class.Name + }, + Method = new KiBoardsTestMethodInfoDto() + { + Name = testMethod?.Method.Name + } + }, + Context = context + }; + + + internal static IEnumerable ToKiBoardsTestCases(this IEnumerable testCases, KiBoardsTestCaseStatus status, KiBoardsTestCaseState state, object context = null) => + testCases.Select(x => x.ToKiBoardsTestCase(null, status, state, context)); + + internal static KiBoardsTestCaseStatus ToKiBoardsTestCaseStatus(this RunSummary summary) + => summary.Failed > 0 ? KiBoardsTestCaseStatus.Failure : summary.Skipped > 0 ? KiBoardsTestCaseStatus.Skipped : KiBoardsTestCaseStatus.Success; + } +} diff --git a/src/KiBoards/Models/KiBoardsTestCaseState.cs b/src/KiBoards/Models/KiBoardsTestCaseState.cs new file mode 100644 index 0000000..6862720 --- /dev/null +++ b/src/KiBoards/Models/KiBoardsTestCaseState.cs @@ -0,0 +1,8 @@ +namespace KiBoards.Models +{ + internal enum KiBoardsTestCaseState + { + Active, + Inactive + } +} diff --git a/src/KiBoards/Models/KiBoardsTestCaseStatus.cs b/src/KiBoards/Models/KiBoardsTestCaseStatus.cs new file mode 100644 index 0000000..c1cafa7 --- /dev/null +++ b/src/KiBoards/Models/KiBoardsTestCaseStatus.cs @@ -0,0 +1,11 @@ +namespace KiBoards.Models +{ + internal enum KiBoardsTestCaseStatus + { + Discovered, + Running, + Success, + Failure, + Skipped + } +} diff --git a/src/KiBoards/Models/KiBoardsTestCaseStatusDto.cs b/src/KiBoards/Models/KiBoardsTestCaseStatusDto.cs new file mode 100644 index 0000000..11043de --- /dev/null +++ b/src/KiBoards/Models/KiBoardsTestCaseStatusDto.cs @@ -0,0 +1,14 @@ +namespace KiBoards.Models +{ + class KiBoardsTestCaseStatusDto + { + public string UniqueId { get; set; } + public string DisplayName { get; set; } + public DateTime UpdatedOn { get; set; } + public string Status { get; set; } + public string State { get; set; } + public string SkipReason { get; set; } + public KiBoardsTestMethodDto TestMethod { get; set; } + public object Context { get; set; } + } +} diff --git a/src/KiBoards/Models/KiBoardsTestClassDto.cs b/src/KiBoards/Models/KiBoardsTestClassDto.cs new file mode 100644 index 0000000..c3fbb69 --- /dev/null +++ b/src/KiBoards/Models/KiBoardsTestClassDto.cs @@ -0,0 +1,10 @@ +using System; + +namespace KiBoards.Models +{ + class KiBoardsTestClassDto + { + public string Name { get; set; } + + } +} diff --git a/src/KiBoards/Models/KiBoardsTestMethodDto.cs b/src/KiBoards/Models/KiBoardsTestMethodDto.cs new file mode 100644 index 0000000..4011dc1 --- /dev/null +++ b/src/KiBoards/Models/KiBoardsTestMethodDto.cs @@ -0,0 +1,8 @@ +namespace KiBoards.Models +{ + class KiBoardsTestMethodDto + { + public KiBoardsTestClassDto TestClass { get; set; } + public KiBoardsTestMethodInfoDto Method { get; set; } + } +} diff --git a/src/KiBoards/Models/KiBoardsTestMethodInfoDto.cs b/src/KiBoards/Models/KiBoardsTestMethodInfoDto.cs new file mode 100644 index 0000000..7f33eab --- /dev/null +++ b/src/KiBoards/Models/KiBoardsTestMethodInfoDto.cs @@ -0,0 +1,8 @@ +namespace KiBoards.Models +{ + class KiBoardsTestMethodInfoDto + { + public string Name { get; set; } + + } +} diff --git a/src/KiBoards/Services/IKiBoardsElasticService.cs b/src/KiBoards/Services/IKiBoardsElasticService.cs new file mode 100644 index 0000000..fb4e1de --- /dev/null +++ b/src/KiBoards/Services/IKiBoardsElasticService.cs @@ -0,0 +1,11 @@ +using KiBoards.Models; + +namespace KiBoards.Services +{ + internal interface IKiBoardsElasticService + { + Task IndexTestCasesAsync(IEnumerable testCases); + Task IndexTestCaseAsync(KiBoardsTestCaseStatusDto testCase); + + } +} \ No newline at end of file diff --git a/src/KiBoards/Services/IKiBoardsTestRunnerService.cs b/src/KiBoards/Services/IKiBoardsTestRunnerService.cs new file mode 100644 index 0000000..4713b0b --- /dev/null +++ b/src/KiBoards/Services/IKiBoardsTestRunnerService.cs @@ -0,0 +1,18 @@ +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace KiBoards.Services +{ + internal interface IKiBoardsTestRunnerService + { + Guid RunId { get; } + + Task BeginTestCasesRunAsync(IEnumerable testCases); + Task StartTestCaseAsync(IXunitTestCase testCase, ITestMethod testMethod); + Task FinishTestCaseAsync(IXunitTestCase testCase, ITestMethod testMethod, ExceptionAggregator exceptionAggregator, RunSummary result); + Task ErrorTestCaseAsync(IXunitTestCase testCase, ITestMethod testMethod, Exception ex); + Task EndTestCasesRunAsync(RunSummary results); + Task ErrorTestCasesRunAsync(IEnumerable testCases, Exception ex); + void SetContext(ITestContextMessage testContext); + } +} \ No newline at end of file diff --git a/src/KiBoards/Services/KiBoardsElasticService.cs b/src/KiBoards/Services/KiBoardsElasticService.cs new file mode 100644 index 0000000..b7c6d40 --- /dev/null +++ b/src/KiBoards/Services/KiBoardsElasticService.cs @@ -0,0 +1,54 @@ +using KiBoards.Models; +using Nest; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace KiBoards.Services +{ + internal class KiBoardsElasticService : IKiBoardsElasticService + { + private readonly IElasticClient _elasticClient; + private readonly IMessageSink _messageSink; + + public KiBoardsElasticService(IElasticClient elasticClient, IMessageSink messageSink) + { + _elasticClient = elasticClient; + _messageSink = messageSink; + } + + public async Task IndexTestCasesAsync(IEnumerable testCases) + { + try + { + _messageSink.OnMessage(new DiagnosticMessage($"Indexing {testCases.Count()} test cases")); + var result = await _elasticClient.IndexManyAsync(testCases); + + if (!result.IsValid) + { + _messageSink.OnMessage(new DiagnosticMessage(result.DebugInformation)); + } + } + catch (Exception ex) + { + _messageSink.OnMessage(new DiagnosticMessage(ex.Message)); + } + } + + public async Task IndexTestCaseAsync(KiBoardsTestCaseStatusDto testCase) + { + try + { + var result = await _elasticClient.IndexDocumentAsync(testCase); + + if (!result.IsValid) + { + _messageSink.OnMessage(new DiagnosticMessage(result.DebugInformation)); + } + } + catch (Exception ex) + { + _messageSink.OnMessage(new DiagnosticMessage(ex.Message)); + } + } + } +} diff --git a/src/KiBoards/Services/KiBoardsElasticServiceExtensions.cs b/src/KiBoards/Services/KiBoardsElasticServiceExtensions.cs new file mode 100644 index 0000000..25bb63d --- /dev/null +++ b/src/KiBoards/Services/KiBoardsElasticServiceExtensions.cs @@ -0,0 +1,29 @@ +using KiBoards.Models; +using Microsoft.Extensions.DependencyInjection; +using Nest; + +namespace KiBoards.Services +{ + internal static class KiBoardsElasticServiceExtensions + { + internal static IServiceCollection AddElasticServices(this IServiceCollection services) + { + return services + .AddSingleton(new ElasticClient(ConfigureIndexes(new ConnectionSettings(new Uri($"http://localhost:9200")) + .MaxRetryTimeout(TimeSpan.FromMinutes(5)) + // This resolves internal errors with bulk index Invalid NEST response built from a successful (200) low level call on POST: /_bulk + .EnableApiVersioningHeader() + .MaximumRetries(3)))) + .AddTransient(); + } + + internal static ConnectionSettings ConfigureIndexes(ConnectionSettings connectionSettings) + { + connectionSettings.DefaultMappingFor(m => m + .IndexName($"kiboards-testcase-status-{DateTime.UtcNow:yyyy-MM}") + .IdProperty(p => p.UniqueId)); + + return connectionSettings; + } + } +} diff --git a/src/KiBoards/Services/KiBoardsTestRunnerService.cs b/src/KiBoards/Services/KiBoardsTestRunnerService.cs new file mode 100644 index 0000000..cb767ac --- /dev/null +++ b/src/KiBoards/Services/KiBoardsTestRunnerService.cs @@ -0,0 +1,79 @@ +using KiBoards.Models; +using System.Reflection; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace KiBoards.Services +{ + internal class KiBoardsTestRunnerService : IKiBoardsTestRunnerService, IDisposable + { + private readonly IMessageSink _messageSink; + private readonly IKiBoardsElasticService _elasticService; + + public Guid RunId { get; private set; } = Guid.NewGuid(); + + public object Context { get; private set; } + + public KiBoardsTestRunnerService(IMessageSink messageSink, IKiBoardsElasticService elasticService) + { + _messageSink = messageSink; + _elasticService = elasticService; + + var version = Assembly.GetExecutingAssembly().GetCustomAttribute()?.InformationalVersion; + messageSink.OnMessage(new DiagnosticMessage($"KiBoards: {version}")); + messageSink.OnMessage(new DiagnosticMessage($"RunId: {RunId}")); + } + + + public void Dispose() + { + //_messageSink.OnMessage(new DiagnosticMessage("KiBoards run finished.")); + } + + public async Task BeginTestCasesRunAsync(IEnumerable testCases) + { + //foreach (var testCase in testCases) + // _messageSink.OnMessage(new DiagnosticMessage($"Discovered: {testCase.UniqueID} {testCase.DisplayName}")); + + await _elasticService.IndexTestCasesAsync(testCases.ToKiBoardsTestCases(KiBoardsTestCaseStatus.Discovered, KiBoardsTestCaseState.Active, Context)); + } + + + public async Task ErrorTestCaseAsync(IXunitTestCase testCase, ITestMethod testMethod, Exception ex) + { + //_messageSink.OnMessage(new DiagnosticMessage($"Fatal: {testCase.UniqueID} ({ex.Message})")); + await Task.CompletedTask; + } + + public async Task FinishTestCaseAsync(IXunitTestCase testCase, ITestMethod testMethod, ExceptionAggregator exceptionAggregator, RunSummary summary) + { + //_messageSink.OnMessage(new DiagnosticMessage($"{(summary.Failed > 0 ? "Failure" : summary.Skipped > 0 ? "Skipped" : "Success")}: {testCase.UniqueID} {testCase.DisplayName} ({summary.Time}s)")); + await _elasticService.IndexTestCaseAsync(testCase.ToKiBoardsTestCase(testMethod, summary.ToKiBoardsTestCaseStatus(), KiBoardsTestCaseState.Inactive, Context)); + } + + public async Task StartTestCaseAsync(IXunitTestCase testCase, ITestMethod testMethod) + { + //_messageSink.OnMessage(new DiagnosticMessage($"Started: {testCase.UniqueID} {testCase.DisplayName}")); + await _elasticService.IndexTestCaseAsync(testCase.ToKiBoardsTestCase(testMethod, KiBoardsTestCaseStatus.Running, KiBoardsTestCaseState.Active, Context)); + } + + + public async Task EndTestCasesRunAsync(RunSummary results) + { + //_messageSink.OnMessage(new DiagnosticMessage("KiBoards run complete.")); + await Task.CompletedTask; + + } + + public async Task ErrorTestCasesRunAsync(IEnumerable testCases, Exception ex) + { + //_messageSink.OnMessage(new DiagnosticMessage($"Fatal: Run {RunId} failed. ({ex.Message})")); + await Task.CompletedTask; + } + + public void SetContext(ITestContextMessage testContext) + { + Context = testContext.Context; + } + } +} diff --git a/src/KiBoards/TestContextFixture.cs b/src/KiBoards/TestContextFixture.cs new file mode 100644 index 0000000..8da59cf --- /dev/null +++ b/src/KiBoards/TestContextFixture.cs @@ -0,0 +1,19 @@ +using Xunit.Abstractions; + +namespace KiBoards +{ + public class TestContextFixture + { + private readonly IMessageSink _messageSink; + + public TestContextFixture(IMessageSink messageSink) + { + _messageSink = messageSink; + } + + public void SetContext(object context) + { + _messageSink.OnMessage(new TestContextMessage(context)); + } + } +} diff --git a/src/KiBoards/TestContextMessage.cs b/src/KiBoards/TestContextMessage.cs new file mode 100644 index 0000000..e8d414c --- /dev/null +++ b/src/KiBoards/TestContextMessage.cs @@ -0,0 +1,12 @@ +namespace KiBoards +{ + internal class TestContextMessage : ITestContextMessage + { + public object Context { get; set; } + + public TestContextMessage(object context) + { + Context = context; + } + } +} diff --git a/src/KiBoards/TestExtensions.cs b/src/KiBoards/TestExtensions.cs new file mode 100644 index 0000000..454fe79 --- /dev/null +++ b/src/KiBoards/TestExtensions.cs @@ -0,0 +1,11 @@ +using System.Reflection; +using Xunit.Abstractions; + +namespace KiBoards +{ + public static class TestExtensions + { + public static ITestCase GetTestCase(this ITestOutputHelper output) + => (output.GetType().GetField("test", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(output) as ITest).TestCase; + } +} diff --git a/src/KiBoards/TestFramework.cs b/src/KiBoards/TestFramework.cs new file mode 100644 index 0000000..b6b9dd3 --- /dev/null +++ b/src/KiBoards/TestFramework.cs @@ -0,0 +1,184 @@ +using System.Reflection; +using KiBoards.Services; +using Microsoft.Extensions.DependencyInjection; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace KiBoards +{ + public class TestFramework : XunitTestFramework, IDisposable + { + private readonly ServiceProvider _serviceProvider; + + public TestFramework(IMessageSink messageSink) + : base(messageSink) + { + IServiceCollection serviceCollection = new ServiceCollection(); + + serviceCollection + .AddSingleton(messageSink) + .AddElasticServices() + .AddSingleton(); + + _serviceProvider = serviceCollection.BuildServiceProvider(); + } + + protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName) + { + return new TestFrameworkExecutor(assemblyName, SourceInformationProvider, DiagnosticMessageSink, _serviceProvider.GetRequiredService()); + } + + public new async void Dispose() + { + await Task.Delay(1); + _serviceProvider.Dispose(); + base.Dispose(); + } + + + private class TestFrameworkExecutor : XunitTestFrameworkExecutor + { + private readonly IKiBoardsTestRunnerService _testRunner; + + public TestFrameworkExecutor(AssemblyName assemblyName, ISourceInformationProvider sourceInformationProvider, IMessageSink diagnosticMessageSink, IKiBoardsTestRunnerService testRunner) + : base(assemblyName, sourceInformationProvider, diagnosticMessageSink) + { + _testRunner = testRunner; + } + + protected override async void RunTestCases(IEnumerable testCases, IMessageSink executionMessageSink, ITestFrameworkExecutionOptions executionOptions) + { + try + { + await _testRunner.BeginTestCasesRunAsync(testCases); + using var assemblyRunner = new TestAssemblyRunner(TestAssembly, testCases, new TestMessageSink(DiagnosticMessageSink, _testRunner), executionMessageSink, executionOptions, _testRunner); + + var results = await assemblyRunner.RunAsync(); + await _testRunner.EndTestCasesRunAsync(results); + } + catch (Exception ex) + { + await _testRunner.ErrorTestCasesRunAsync(testCases, ex); + } + } + } + + + + private class TestAssemblyRunner : XunitTestAssemblyRunner + { + private readonly IKiBoardsTestRunnerService _testRunner; + private readonly IMessageSink _messageSink; + + public TestAssemblyRunner(ITestAssembly testAssembly, IEnumerable testCases, IMessageSink diagnosticMessageSink, IMessageSink executionMessageSink, ITestFrameworkExecutionOptions executionOptions, IKiBoardsTestRunnerService testRunner) + : base(testAssembly, testCases, diagnosticMessageSink, executionMessageSink, executionOptions) + { + _testRunner = testRunner; + _messageSink = diagnosticMessageSink; + } + + + + + protected override async Task RunTestCollectionAsync(IMessageBus messageBus, ITestCollection testCollection, IEnumerable testCases, CancellationTokenSource cancellationTokenSource) + { + var collectionRunner = new TestCollectionRunner(testCollection, testCases, DiagnosticMessageSink, messageBus, TestCaseOrderer, new ExceptionAggregator(Aggregator), cancellationTokenSource, _testRunner); + return await collectionRunner.RunAsync(); + } + + protected override string GetTestFrameworkDisplayName() + { + var version = Assembly.GetExecutingAssembly().GetCustomAttribute()?.InformationalVersion; + return $"KiBoards {version}"; + } + + protected override Task AfterTestAssemblyStartingAsync() + { + _messageSink.OnMessage(new DiagnosticMessage("AfterTestAssemblyStartingAsync")); + return base.AfterTestAssemblyStartingAsync(); + } + + + protected override Task BeforeTestAssemblyFinishedAsync() + { + _messageSink.OnMessage(new DiagnosticMessage("BeforeTestAssemblyFinishedAsync")); + return base.BeforeTestAssemblyFinishedAsync(); + } + } + + + private class TestCollectionRunner : XunitTestCollectionRunner + { + private readonly IKiBoardsTestRunnerService _testRunner; + + public TestCollectionRunner(ITestCollection testCollection, IEnumerable testCases, IMessageSink diagnosticMessageSink, IMessageBus messageBus, ITestCaseOrderer testCaseOrderer, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource, IKiBoardsTestRunnerService testRunner) + : base(testCollection, testCases, diagnosticMessageSink, messageBus, testCaseOrderer, aggregator, cancellationTokenSource) + { + _testRunner = testRunner; + } + + protected override Task RunTestClassAsync(ITestClass testClass, IReflectionTypeInfo @class, IEnumerable testCases) + => new TestClassRunner(testClass, @class, testCases, DiagnosticMessageSink, MessageBus, TestCaseOrderer, new ExceptionAggregator(Aggregator), CancellationTokenSource, CollectionFixtureMappings, _testRunner) + .RunAsync(); + } + + + private class TestClassRunner : XunitTestClassRunner + { + private readonly IKiBoardsTestRunnerService _testRunner; + + public TestClassRunner(ITestClass testClass, IReflectionTypeInfo @class, IEnumerable testCases, IMessageSink diagnosticMessageSink, IMessageBus messageBus, ITestCaseOrderer testCaseOrderer, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource, IDictionary collectionFixtureMappings, IKiBoardsTestRunnerService testRunner) + : base(testClass, @class, testCases, diagnosticMessageSink, messageBus, testCaseOrderer, aggregator, cancellationTokenSource, collectionFixtureMappings) + { + _testRunner = testRunner; + } + + protected override Task RunTestMethodAsync(ITestMethod testMethod, IReflectionMethodInfo method, IEnumerable testCases, object[] constructorArguments) + => new TestMethodRunner(testMethod, Class, method, testCases, DiagnosticMessageSink, new TestResultBus(MessageBus), new ExceptionAggregator(Aggregator), CancellationTokenSource, constructorArguments, _testRunner) + .RunAsync(); + + protected override async Task RunTestMethodsAsync() + { + return await base.RunTestMethodsAsync(); + } + } + + + + private class TestMethodRunner : XunitTestMethodRunner + { + private readonly IKiBoardsTestRunnerService _testRunner; + private readonly TestResultSink _resultSink; + private readonly TestResultBus _resultBus; + + public TestMethodRunner(ITestMethod testMethod, IReflectionTypeInfo @class, IReflectionMethodInfo method, IEnumerable testCases, IMessageSink diagnosticMessageSink, TestResultBus messageBus, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource, object[] constructorArguments, IKiBoardsTestRunnerService testRunner) + : base(testMethod, @class, method, testCases, diagnosticMessageSink, messageBus, aggregator, cancellationTokenSource, constructorArguments) + + { + _resultBus = messageBus; + _testRunner = testRunner; + } + + protected override async Task RunTestCaseAsync(IXunitTestCase testCase) + { + try + { + await _testRunner.StartTestCaseAsync(testCase, TestMethod); + var result = await base.RunTestCaseAsync(testCase); + + var testResult = _resultBus.TestResult; + + await _testRunner.FinishTestCaseAsync(testCase, TestMethod, Aggregator, result); + + return result; + } + catch (Exception ex) + { + await _testRunner.ErrorTestCaseAsync(testCase, TestMethod, ex); + throw; + } + } + } + } +} + diff --git a/src/KiBoards/TestMessageSink.cs b/src/KiBoards/TestMessageSink.cs new file mode 100644 index 0000000..42139c2 --- /dev/null +++ b/src/KiBoards/TestMessageSink.cs @@ -0,0 +1,158 @@ +using KiBoards.Services; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace KiBoards +{ + internal class TestMessageSink : IMessageSink + { + private readonly IKiBoardsTestRunnerService _testRunner; + private IMessageSink _messageSink; + + internal TestMessageSink(IMessageSink messageSink, IKiBoardsTestRunnerService testRunner) + { + _messageSink = messageSink; + _testRunner = testRunner; + } + + private void LogMessage(string message) + { + _messageSink.OnMessage(new DiagnosticMessage(message)); + } + + private void LogTestCase(string messageType, ITestCase testCase) + { + LogMessage($"{messageType}: TestCase.UniqueID: {testCase.UniqueID}"); + LogMessage($"{messageType}: TestCase.DisplayName: {testCase.DisplayName}"); + LogMessage($"{messageType}: TestCase.Traits.Count: {testCase.Traits.Count}"); + + if (testCase.SourceInformation != null) + { + LogMessage($"{messageType}: TestCase.SourceInformation.FileName: {testCase.SourceInformation.FileName}"); + LogMessage($"{messageType}: TestCase.SourceInformation.LineNumber: {testCase.SourceInformation.LineNumber}"); + } + } + + + public bool OnMessage(IMessageSinkMessage message) + { + HandleMessageSinkMessage(message); + return _messageSink.OnMessage(message); + } + + private void HandleMessageSinkMessage(IMessageSinkMessage message) + { + switch (message) + { + + case ITestContextMessage testContext: + LogMessage($"TestContext: {testContext}"); + _testRunner.SetContext(testContext); + + break; + + case ITestAssemblyStarting testAssemblyStarting: + LogMessage($"TestAssemblyStarting: StartTime: {testAssemblyStarting.StartTime}"); + LogMessage($"TestAssemblyStarting: TestFrameworkDisplayName: {testAssemblyStarting.TestFrameworkDisplayName}"); + LogMessage($"TestAssemblyStarting: TestEnvironment: {testAssemblyStarting.TestEnvironment}"); + LogMessage($"TestAssemblyStarting: TestCases.Count: {testAssemblyStarting.TestCases.Count()}"); + break; + + case ITestCollectionStarting testCollectionStarting: + LogMessage($"TestCollectionStarting: TestCollection.DisplayName: {testCollectionStarting.TestCollection.DisplayName}"); + LogMessage($"TestCollectionStarting: TestCollection.UniqueID: {testCollectionStarting.TestCollection.UniqueID}"); + LogMessage($"TestCollectionStarting: TestCollection.TestCases.Count: {testCollectionStarting.TestCases.Count()}"); + LogMessage($"TestCollectionStarting: TestAssembly.Assembly.Name: {testCollectionStarting.TestAssembly.Assembly.Name}"); + break; + + + case ITestMethodStarting testMethodStarting: + LogMessage($"TestMethodStarting: TestCollection.DisplayName: {testMethodStarting.TestCollection.DisplayName}"); + LogMessage($"TestMethodStarting: TestCollection.UniqueID: {testMethodStarting.TestCollection.UniqueID}"); + LogMessage($"TestMethodStarting: TestCollection.TestAssembly.Assembly.AssemblyPath: {testMethodStarting.TestCollection.TestAssembly.Assembly.AssemblyPath}"); + LogMessage($"TestMethodStarting: TestCases.Count: {testMethodStarting.TestCases.Count()}"); + + LogMessage($"TestMethodStarting: TestClass.Class.Name: {testMethodStarting.TestClass.Class.Name}"); + break; + + case ITestCaseStarting testCaseStarting: + LogMessage("TestCaseStarting"); + break; + + case ITestStarting testStarting: + LogMessage($"TestStarting: Test.DisplayName: {testStarting.Test.DisplayName}"); + break; + + case ITestClassConstructionStarting classConstructionStarting: + LogMessage($"TestClassConstructionStarting: Test.DisplayName: {classConstructionStarting.Test.DisplayName}"); + LogMessage($"TestClassConstructionStarting: Test.TestCase.DisplayName: {classConstructionStarting.Test.TestCase.DisplayName}"); + LogMessage($"TestClassConstructionStarting: Test.TestCase.UniqueID: {classConstructionStarting.Test.TestCase.UniqueID}"); + LogMessage($"TestClassConstructionStarting: Test.TestCase.TestMethod.Method.Name: {classConstructionStarting.Test.TestCase.TestMethod.Method.Name}"); + break; + + case ITestClassConstructionFinished classConstructionFinished: + // Code to handle Xunit.Sdk.TestClassConstructionFinished case + break; + + + case ITestSkipped testSkipped: + // Code to handle Xunit.Sdk.TestSkipped case + break; + + case ITestPassed testPassed: + LogMessage($"TestPassed: Output: {testPassed.Output}"); + LogMessage($"TestPassed: ExcecutionTime: {testPassed.ExecutionTime}"); + LogMessage($"TestPassed: Test.DisplayName: {testPassed.Test.DisplayName}"); + LogMessage($"TestPassed: TestCase.UniqueID: {testPassed.TestCase.UniqueID}"); + LogMessage($"TestPassed: TestCase.DisplayName: {testPassed.TestCase.DisplayName}"); + LogMessage($"TestPassed: TestCases.Count: {testPassed.TestCases.Count()}"); + + // Code to handle Xunit.Sdk.TestPassed case + break; + + case ITestFailed testFailed: + LogMessage($"TestFailed: ExecutionTime: {testFailed.ExecutionTime}"); + LogMessage($"TestFailed: Messages: {string.Join('\n', testFailed.Messages)}"); + LogMessage($"TestFailed: Output: {testFailed.Output}"); + // Code to handle Xunit.Sdk.TestFailed case + break; + + case ITestFinished testFinished: + // Code to handle Xunit.Sdk.TestFinished case + break; + + case ITestCaseFinished testCaseFinished: + // Code to handle Xunit.Sdk.TestCaseFinished case + break; + + + case ITestMethodFinished testMethodFinished: + // Code to handle Xunit.Sdk.TestMethodFinished case + break; + + case ITestClassStarting testClassStarting: + break; + + case ITestOutput TestOutput: + break; + + case ITestClassFinished testClassFinished: + break; + + case ITestCollectionFinished testCollectionFinished: + break; + + case ITestAssemblyFinished testAssemblyFinished: + LogMessage($"TestAssemblyFinished: TestsRun: {testAssemblyFinished.TestsRun}"); + LogMessage($"TestAssemblyFinished: TestsFailed: {testAssemblyFinished.TestsFailed}"); + LogMessage($"TestAssemblyFinished: TestsSkipped: {testAssemblyFinished.TestsSkipped}"); + LogMessage($"TestAssemblyFinished: ExecutionTime: {testAssemblyFinished.ExecutionTime}"); + break; + + default: + LogMessage($"UNKNOWN: {message.GetType().Name}: {message}"); + break; + } + } + } +} diff --git a/src/KiBoards/TestResultBus.cs b/src/KiBoards/TestResultBus.cs new file mode 100644 index 0000000..6aa1c6b --- /dev/null +++ b/src/KiBoards/TestResultBus.cs @@ -0,0 +1,28 @@ +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace KiBoards +{ + internal class TestResultBus : IMessageBus + { + private readonly IMessageBus _messageBus; + + public ITestResultMessage TestResult { get; private set; } + + internal TestResultBus(IMessageBus messsageBus) => _messageBus = messsageBus ?? throw new ArgumentNullException(nameof(messsageBus)); + + + public bool QueueMessage(IMessageSinkMessage message) + { + if (message is ITestResultMessage result) + TestResult = result; + + return _messageBus.QueueMessage(message); + } + + public void Dispose() + { + _messageBus.Dispose(); + } + } +} diff --git a/src/KiBoards/TestResultSink.cs b/src/KiBoards/TestResultSink.cs new file mode 100644 index 0000000..a49a4cd --- /dev/null +++ b/src/KiBoards/TestResultSink.cs @@ -0,0 +1,24 @@ +using Xunit.Abstractions; + +namespace KiBoards +{ + internal class TestResultSink : IMessageSink + { + private IMessageSink _messageSink; + + public ITestResultMessage TestResult { get; private set; } + + internal TestResultSink(IMessageSink messageSink) + { + _messageSink = messageSink; + } + + public bool OnMessage(IMessageSinkMessage message) + { + if (message is ITestResultMessage result) + TestResult = result; + + return _messageSink.OnMessage(message); + } + } +}