Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proto Stage 1 - Go test output parser #1

Merged
merged 2 commits into from
Mar 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
# @global-owner1 and @global-owner2 will be requested for
# review when someone opens a pull request.
@alqh
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.DS_Store
.idea
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Fitogether

Inspired by the workflow of [_Fit_](http://fit.c2.com/), Fitogether enables collaboration and communication in software development.

## Concept

<img src="./docs/assets/images/Fit.png" width="650"/>

Multiple stakeholders (technical and non-technical) collaborate together to produce a cFit Document that describes the software behaviour in a language that is understandable and clear to all. This document should be easy enough to understand that it can serve as a manual to ordinary users, a promise to your users of what the software does.

The cFit Document feeds into the process of developing the running software. Each part of the document sets an expectation of how the software should behave, like an acceptance criteria, which is then translated into one or more tests written as part of the UI or service's test. Typically a UI or a service has different granularity of tests (testing pyramid), therefore, the one expectation could encompass a few unit tests, a few component tests and an integration test.

All the tests results then feeds back up and collated to indicate if the expectation in the Fit Document has been met or not.

A cFit report should show:

* the expectations of the software
* if the expectations of the software has been met. This is measured if all tests related to that expectation pass.
* a breakdown of where the expectation is verified. This is the list of where the tests are.

75 changes: 75 additions & 0 deletions docs/USE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Use Fitogether

## Creating cFit Documents

### Unit
Each cFit document should represent a unit of software.

Each unit has expectations of how it behave, and can include interactions with other units in order to deliver the functionality that it owns.

This unit is documented in a single markdown file.

The fitogether tool will parse the markdown to determine the expectations to match.

Defining expectations:

* Each header is an expectation. This can be `h2`, `h3`, `h4` and so forth.
* The expectation is referenced by its coded value, which is the first non-spaced word on the header.

```markdown
# Tagging Blog Post

// Format <heading level> <codedValue> <text describing the expectation>
## T1.v2 Add a tag to a blog post

### A1 The tag must have been deleted

### A2 The user must have permission to add a tag to blog post
```

### Categories

Multiple cFit documents can be grouped under a category of functionality, which in turn, can be grouped under a larger category of functionality.

Each category is a directory.

An example could be:

```
blogs
|-- post
|-- tagging-blog-post.md
|-- feeds
|-- subscribe-new-feeds.md
|-- unsubscribe-via-email.md
```

## Creating Tests to Validate cFit Expectations

The testing library used for running tests in for a language will produce a test report. This test report will be parsed by fitogether tool to match the test to the expectation.

Each expectation can be referenced by its full URI:

```
// Format: [<dir_path>]-<filename>-[<codedValue>]
blogs/post/tagging-blog-post/t1.v2/a2
```

Depending on the language support, here is how each test are tagged:

### Go

Add the URI of the expecation in the end of the the test name.

```go
// Format: t.Run("..description of test... @<URI of expectation>")

func TestAssignBlogPostHandler(t *testing.T) {
t.Run("Should remove tags to blog post @blogs/post/tagging-blog-post/t1.v2/a1", ....)
}

func TestBlogPostRepository(t *testing.T) {
t.Run("Soft delete tag on blog post @blogs/post/tagging-blog-post/t1.v2/a1", ....)
}
```

158 changes: 158 additions & 0 deletions docs/assets/drawio/Fit.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<mxfile host="app.diagrams.net" modified="2024-03-16T03:03:55.285Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" etag="4GVYUySkvPvQ5tCx2QE3" version="24.0.7" type="device">
<diagram name="Page-1" id="53M_2jYgaUl9bHfNDvYw">
<mxGraphModel dx="2069" dy="819" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="P_TPIv7538cp4Sw5QN1q-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-1" target="P_TPIv7538cp4Sw5QN1q-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-1" value="Developers" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="130" y="380" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-2">
<mxGeometry relative="1" as="geometry">
<mxPoint x="295" y="470" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-2" value="Designers" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="280" y="520" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-5" target="P_TPIv7538cp4Sw5QN1q-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-5" value="Product Managers" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="429" y="380" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-6" target="P_TPIv7538cp4Sw5QN1q-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-6" value="Support" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="150" y="280" width="20" height="40" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-7" target="P_TPIv7538cp4Sw5QN1q-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-7" value="Marketing" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="429" y="280" width="21" height="40" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-8" target="P_TPIv7538cp4Sw5QN1q-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-8" value="Users" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="390" y="510" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeColor=#00994D;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-14" target="P_TPIv7538cp4Sw5QN1q-28">
<mxGeometry relative="1" as="geometry">
<mxPoint x="295" y="190" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-14" value="Collaborate and agree on software behaviour" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;textShadow=0;fillColor=#CCFFCC;" vertex="1" parent="1">
<mxGeometry x="240" y="355" width="110" height="110" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-15" target="P_TPIv7538cp4Sw5QN1q-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-15" value="Testers" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="170" y="510" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.25;entryDx=0;entryDy=0;exitX=1;exitY=0.25;exitDx=0;exitDy=0;strokeColor=#00994D;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-28" target="P_TPIv7538cp4Sw5QN1q-32">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-34" value="sets expectations" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="P_TPIv7538cp4Sw5QN1q-33">
<mxGeometry x="-0.1444" y="1" relative="1" as="geometry">
<mxPoint x="1" y="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-28" value="cFit Document" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="207.5" y="120" width="175" height="90" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-30" value="- Clear business requirements&lt;br&gt;- Describe software behaviour&lt;br&gt;(functionally, not the UI)&lt;br&gt;- Language used is understandable and aligned among stakeholders&amp;nbsp;&lt;br&gt;(ubiquitous language)" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;labelBackgroundColor=#FFF6A6;spacing=5;spacingTop=5;spacingBottom=5;" vertex="1" parent="1">
<mxGeometry x="-60" y="115" width="240" height="100" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.75;entryDx=0;entryDy=0;exitX=0;exitY=0.75;exitDx=0;exitDy=0;dashed=1;strokeColor=#FF6666;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-32" target="P_TPIv7538cp4Sw5QN1q-28">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-36" value="pass / fail" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontColor=#FF3333;" vertex="1" connectable="0" parent="P_TPIv7538cp4Sw5QN1q-35">
<mxGeometry x="0.1709" y="3" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-45" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=0;entryDx=0;entryDy=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;strokeColor=#00994D;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-32" target="P_TPIv7538cp4Sw5QN1q-37">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-54" value="Help form&lt;br&gt;test cases" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="P_TPIv7538cp4Sw5QN1q-45">
<mxGeometry x="0.5924" y="-1" relative="1" as="geometry">
<mxPoint x="-41" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-46" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.25;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;strokeColor=#00994D;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-32" target="P_TPIv7538cp4Sw5QN1q-63">
<mxGeometry relative="1" as="geometry">
<mxPoint x="995" y="360" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-58" value="Help form&lt;br&gt;test cases" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="P_TPIv7538cp4Sw5QN1q-46">
<mxGeometry x="0.7333" y="2" relative="1" as="geometry">
<mxPoint x="-37" y="-4" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-32" value="Running Software" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="800" y="120" width="150" height="90" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-37" value="UI" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="727" y="360" width="100" height="50" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.347;entryY=1.011;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;fillColor=#f8cecc;strokeColor=#FF3333;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-37" target="P_TPIv7538cp4Sw5QN1q-32">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="777" y="310" />
<mxPoint x="852" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-55" value="pass / fail" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontColor=#FF3333;" vertex="1" connectable="0" parent="P_TPIv7538cp4Sw5QN1q-52">
<mxGeometry x="-0.643" y="-1" relative="1" as="geometry">
<mxPoint x="32" y="10" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-59" value="" style="verticalLabelPosition=bottom;verticalAlign=top;html=1;shape=mxgraph.basic.acute_triangle;dx=0.5;" vertex="1" parent="1">
<mxGeometry x="795" y="365" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-60" value="Tests" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=10;" vertex="1" parent="1">
<mxGeometry x="790" y="375" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-63" value="BE / Services" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="920" y="375" width="245" height="200" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-39" value="Data&lt;br&gt;Storage" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="P_TPIv7538cp4Sw5QN1q-63">
<mxGeometry x="10" y="40" width="100" height="50" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-40" value="Events" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="P_TPIv7538cp4Sw5QN1q-63">
<mxGeometry x="120" y="70" width="100" height="50" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-41" value="3rd Party&lt;br&gt;(External)" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="P_TPIv7538cp4Sw5QN1q-63">
<mxGeometry x="10" y="110" width="100" height="50" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-61" value="" style="verticalLabelPosition=bottom;verticalAlign=top;html=1;shape=mxgraph.basic.acute_triangle;dx=0.5;" vertex="1" parent="P_TPIv7538cp4Sw5QN1q-63">
<mxGeometry x="190" y="-10" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-62" value="Tests" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=10;" vertex="1" parent="P_TPIv7538cp4Sw5QN1q-63">
<mxGeometry x="185" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-65" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.813;entryY=1.033;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;strokeColor=#FF3333;" edge="1" parent="1" source="P_TPIv7538cp4Sw5QN1q-63" target="P_TPIv7538cp4Sw5QN1q-32">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1043" y="270" />
<mxPoint x="922" y="270" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="P_TPIv7538cp4Sw5QN1q-66" value="pass / fail" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontColor=#FF3333;" vertex="1" connectable="0" parent="P_TPIv7538cp4Sw5QN1q-65">
<mxGeometry x="-0.5116" y="1" relative="1" as="geometry">
<mxPoint x="29" y="4" as="offset" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
Binary file added docs/assets/images/Fit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
output-results
Loading