github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/docs/DeveloperGenerateTest.md (about)

     1  # Generating Tests
     2  
     3  ## Context
     4  
     5  We rely on Ginkgo and Gomega as the core of our E2E functional test framework. Ginkgo allows you to write expressive BDD style tests that act as specifications by example. The intent is to allow a team to write specifications, which we call a spec outline, that look like this:
     6  
     7  ```
     8  BookSuiteDescribe: Book service E2E tests
     9      Describe: Categorizing book length @book
    10          When: the book has more than 300 pages @slow
    11              It: should be a novel
    12          When: the book has fewer than 300 pages @fast
    13              It: should be a short story
    14  
    15      Describe: Creating bookmarks in a book @book, @bookmark, @parallel
    16          It: has no bookmarks by default
    17          It: can add bookmarks
    18  
    19  ```
    20  
    21  and be able to generate skeleton Ginkgo Test Files that look like this:
    22  
    23  ```golang
    24  package books
    25  
    26  /* This was generated from a template file. Please feel free to update as necessary!
    27     a couple things to note:
    28      - Remember to implement specific logic of the service/domain you are trying to test if it not already there in the pkg/
    29  
    30      - To include the tests as part of the E2E Test suite:
    31         - Update the pkg/framework/describe.go to include the `Describe func` of this new test suite, If you haven't already done so.
    32         - Import this new package into the cmd/e2e_test.go
    33  */
    34  
    35  import (
    36  	. "github.com/onsi/ginkgo/v2"
    37  	. "github.com/onsi/gomega"
    38  
    39  	"context"
    40  	"encoding/json"
    41  	"fmt"
    42  	"strings"
    43  	"time"
    44  
    45  	"github.com/redhat-appstudio/e2e-tests/pkg/framework"
    46  	//framework imports edit as required
    47  	"github.com/redhat-appstudio/e2e-tests/pkg/constants"
    48  	"github.com/redhat-appstudio/e2e-tests/pkg/utils"
    49  )
    50  
    51  var _ = framework.BookSuiteDescribe("Book service E2E tests", func() {
    52  
    53  	defer GinkgoRecover()
    54  	var err error
    55  	var f *framework.Framework
    56  	// use 'f' to access common controllers or the specific service controllers within the framework
    57  	BeforeAll(func() {
    58  		// Initialize the tests controllers
    59  		f, err = framework.NewFramework()
    60  		Expect(err).NotTo(HaveOccurred())
    61  	})
    62  
    63  	Describe("Categorizing book length  ", Label("book"), func() {
    64  		// Declare variables here.
    65  
    66  		When("the book has more than 300 pages  ", Label("slow"), func() {
    67  
    68  			It("should be a novel", func() {
    69  
    70  				// Implement test and assertions here
    71  
    72  			})
    73  
    74  		})
    75  
    76  		When("the book has fewer than 300 pages  ", Label("fast"), func() {
    77  
    78  			It("should be a short story", func() {
    79  
    80  				// Implement test and assertions here
    81  
    82  			})
    83  
    84  		})
    85  
    86  	})
    87  
    88  	Describe("Creating bookmarks in a book  ", Label("book"), Label("bookmark"), Label("parallel"), func() {
    89  		// Declare variables here.
    90  
    91  		It("has no bookmarks by default", func() {
    92  
    93  			// Implement test and assertions here
    94  
    95  		})
    96  
    97  		It("can add bookmarks", func() {
    98  
    99  			// Implement test and assertions here
   100  
   101  		})
   102  
   103  	})
   104  
   105  })
   106  
   107  ```
   108  
   109  or parse Ginkgo Test Files that have large amounts of code, like [build.go](../tests/build/build.go), and generate spec outlines that looks like this.
   110  
   111  ```
   112  BuildSuiteDescribe: Build service E2E tests @build, @HACBS
   113    Describe: test PaC component build @github-webhook, @pac-build, @pipeline
   114      When: a new component without specified branch is created @pac-custom-default-branch
   115        It: correctly targets the default branch (that is not named 'main') with PaC
   116        It: triggers a PipelineRun
   117        It: a related PipelineRun and Github webhook should be deleted after deleting the component
   118        It: PR branch should not exists in the repo
   119      When: a new component with specified custom branch branch is created
   120        It: triggers a PipelineRun
   121        It: should lead to a PaC init PR creation
   122        It: the PipelineRun should eventually finish successfully
   123        It: eventually leads to a creation of a PR comment with the PipelineRun status report
   124      When: the PaC init branch is updated
   125        It: eventually leads to triggering another PipelineRun
   126        It: PipelineRun should eventually finish
   127        It: eventually leads to another update of a PR with a comment about the PipelineRun status report
   128      When: the PaC init branch is merged
   129        It: eventually leads to triggering another PipelineRun
   130        It: pipelineRun should eventually finish
   131      When: the component is removed and recreated (with the same name in the same namespace)
   132        It: should no longer lead to a creation of a PaC PR
   133  
   134    Describe: Creating component with container image source
   135      It: should not trigger a PipelineRun
   136  
   137    Describe: PLNSRVCE-799 - test pipeline selector @pipeline-selector
   138      It: a specific Pipeline bundle should be used and additional pipeline params should be added to the PipelineRun if all WhenConditions match
   139      It: default Pipeline bundle should be used and no additional Pipeline params should be added to the PipelineRun if one of the WhenConditions does not match
   140  
   141    Describe: A secret with dummy quay.io credentials is created in the testing namespace
   142      It: should override the shared secret
   143      It: should not be possible to push to quay.io repo (PipelineRun should fail)
   144  
   145  ```
   146  
   147  ## How it works
   148  
   149  We leverage existing Ginkgo's tool set to be able to do this translation back and forth. 
   150  * `ginkgo outline` we use to be able to generate the initial spec outline for our internal model based on what is in the file Ginkgo Test File. This command depends on the GoLang AST to generates the output. 
   151  * `ginkgo generate` we use to pass a customize template and data so that it can render a spec file using Ginkgo's extensive use of closures to allow us to build a descriptive spec hierarchy. 
   152  
   153  ## Schema
   154  
   155  The text outline file must be in the following format:
   156  
   157   * Each line MUST be in key/value format using `:` as delimiter
   158      * Each key MUST be a Ginkgo DSL word for Container and Subject nodes, `Describe/When/Context/It/By/DescribeTable/Entry`
   159      * The value is essentially the description text of the container
   160   * All lines MUST be nested, by using spaces, to represent the logical tree hierarchy of the specification
   161   * The first line MUST be a framework decorator function type `Describe` node that will get implemented in `/pkg/framework/describe.go`
   162   * To assign Labels: 
   163   		* each string intended to be a label MUST be prefixed with `@`
   164      * the set of labels MUST be a comma separated list
   165      * they MUST be assigned AFTER the description text
   166   * When using the `DescribeTable` key, the proceeding nested lines MUST have the `Entry` or `By` key or Ginkgo will not render the template properly
   167  
   168  For the time being we don't support any of Ginkgo's Setup/Teardown nodes. We could technically graph it together from the text outline but it won't render with our base template. The important thing is to expressively model the behavior to test. Test developers will be able to insert Setup/Teardown nodes where they see fit when the spec has been rendered. 
   169  
   170  
   171  ## Prerequisite
   172  
   173  Before generating anything make sure you have Ginkgo in place. To install Ginkgo:
   174  
   175  `go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo`
   176  
   177  ## Team specific template
   178  Teams can create their own templates according to their needs.
   179  These should utilize the provided `specs.tmpl` by including the following line wherever they want their specs to be. (do not forget the dot!) 
   180  
   181  `{{ template "specs" . }}`
   182  
   183  Everything needed to get started is in the [templates/default](../templates/default) directory.
   184  
   185  Please see the provided [recommended](../templates/default/recommended.tmpl) and [barebones](../templates/default/barebones.tmpl) templates.
   186  Copy them and make your own.
   187   
   188   ## Usage
   189  
   190   ### Printing a text outline of an existing ginkgo spec file
   191   This will generate the outline and output to your terminal. If you would like to save the outline to a file refer to the next section.
   192  
   193  `./mage PrintOutlineOfGinkgoSpec tests/<subdirectory>/<test-file>.go`
   194  
   195  ```bash
   196  $ ./mage PrintOutlineOfGinkgoSpec tests/books/books.go
   197  tests/books/books.goI0622 22:11:30.391491   19273 testcasemapper.go:26] Mapping outline from a Ginkgo test file, tests/books/books.go
   198  I0622 22:11:30.395240   19273 testcasemapper.go:40] Printing outline:
   199  
   200  BookSuiteDescribe: Book service E2E tests
   201    Describe: Categorizing book length  @book
   202      When: the book has more than 300 pages  @slow
   203        It: Should be a novel
   204      When: the book has fewer than 300 pages  @fast
   205        It: should be a short story
   206  
   207    Describe: Creating bookmarks in a book  @book, @bookmark, @parallel
   208      It: Has no bookmarks by default
   209      It: Can add bookmarks
   210  
   211    DescribeTable: Reading invalid books always errors is table
   212      Entry: Empty book
   213      Entry: Only title
   214      Entry: Only author
   215      Entry: Missing pages
   216  
   217  ```
   218  ### Generating the text outline file from an existing ginkgo spec file
   219  This will generate the outline and output to a text file to the desired file location
   220  
   221  `./mage GenerateTextOutlineFromGinkgoSpec tests/<subdirectory>/<test-file>.go <dest>/<sub-path>/<file>`
   222  
   223  ```bash
   224  $ ./mage GenerateTextOutlineFromGinkgoSpec tests/books/books.go /tmp/outlines/books.outline
   225  I0622 22:19:41.857966   20923 testcasemapper.go:26] Mapping outline from a Ginkgo test file, tests/books/books.go
   226  I0622 22:19:41.865725   20923 testcasemapper.go:70] Mapping outline to a text file, /tmp/outlines/books.outline
   227  I0622 22:19:41.865837   20923 textspec.go:67] successfully written to /tmp/outlines/books.outline
   228  
   229  ```
   230   
   231   ### Generating a generic Ginkgo spec file from an existing text outline file
   232   This will generate a generic Ginkgo spec in a subdirectory within our tests directory
   233  
   234   `./mage GenerateGinkgoSpecFromTextOutline <path>/<to>/<outline> <subpath-under-tests>/<filename>.go`
   235  
   236   ```bash
   237   $ ./mage GenerateGinkoSpecFromTextOutline dummy_test.outline books/books.go
   238  I0622 22:14:22.140583   20356 testcasemapper.go:58] Mapping outline from a text file, dummy_test.outline
   239  I0622 22:14:22.140673   20356 testcasemapper.go:47] Mapping outline to a Ginkgo test file, books/books.go
   240  I0622 22:14:22.140841   20356 ginkgosspec.go:242] Creating new test package directory and spec file tests/books/books.go.
   241   ```
   242  As noted above, this command will create a new package under the `tests/` directory and a test spec file `<filename>.go` for you. It will contain some basic imports but more importantly it will generate a basic structured Ginkgo spec skeleton that you can code against.
   243  
   244  ### Generating a team specific Ginkgo spec file from an existing text outline file
   245  This will generate the Ginkgo spec in a subdirectory within our tests directory using a team specific template provided by user. Please see the [Team specific template](#team-specific-template) section.
   246  
   247  Feel free to use the provided [testOutline](../templates/default/testOutline) file for testing.
   248  
   249  `./mage GenerateTeamSpecificGinkgoSpecFromTextOutline <path>/<to>/<outline> <path>/<to>/<team-specific-template> <subpath-under-tests>/<filename>.go`
   250  
   251  ```bash
   252  ➜ ./mage GenerateTeamSpecificGinkgoSpecFromTextOutline templates/default/testOutline templates/default/recommended.tmpl tests/template_poc/template_poc.go
   253  I0219 15:42:17.808595  351210 magefile.go:755] Mapping outline from a text file, templates/default/testOutline
   254  I0219 15:42:17.808685  351210 magefile.go:762] Mapping outline to a Ginkgo spec file, tests/template_poc/template_poc.go
   255  I0219 15:42:17.809210  351210 ginkgosspec.go:144] Creating new test package directory and spec file /home/tnevrlka/Work/e2e-tests/tests/template_poc/template_poc.go.
   256  ```
   257  
   258  ### Printing a text outline in JSON format of an existing ginkgo spec file
   259   This will generate the outline and output to your terminal in JSON format. This is the format we use when rendering the template. You can pipe this output to tools like `jq` for formatting and filtering. This would only be useful for troubleshooting purposes 
   260  
   261  `./mage PrintJsonOutlineOfGinkgoSpec tests/<subdirectory>/<test-file>.go`
   262  
   263  ```bash
   264  $ ./mage PrintJsonOutlineOfGinkgoSpec tests/books/books.go 
   265  I0622 22:28:15.661455   23214 testcasemapper.go:26] Mapping outline from a Ginkgo test file, tests/books/books.go
   266  [{"Name":"BookSuiteDescribe","Text":"Book service E2E tests","Labels":[],"Nodes":[{"Name":"Describe","Text":"Categorizing book length ","Labels":["book"],"Nodes":[{"Name":"When","Text":"the book has more than 300 pages ","Labels":["slow"],"Nodes":[{"Name":"It","Text":"Should be a novel","Labels":[],"Nodes":[],"InnerParentContainer":false,"LineSpaceLevel":0}],"InnerParentContainer":false,"LineSpaceLevel":0},{"Name":"When","Text":"the book has fewer than 300 pages ","Labels":["fast"],"Nodes":[{"Name":"It","Text":"should be a short story","Labels":[],"Nodes":[],"InnerParentContainer":false,"LineSpaceLevel":0}],"InnerParentContainer":false,"LineSpaceLevel":0}],"InnerParentContainer":true,"LineSpaceLevel":0},{"Name":"Describe","Text":"Creating bookmarks in a book ","Labels":["book","bookmark","parallel"],"Nodes":[{"Name":"It","Text":"Has no bookmarks by default","Labels":[],"Nodes":[],"InnerParentContainer":false,"LineSpaceLevel":0},{"Name":"It","Text":"Can add bookmarks","Labels":[],"Nodes":[],"InnerParentContainer":false,"LineSpaceLevel":0}],"InnerParentContainer":true,"LineSpaceLevel":0},{"Name":"DescribeTable","Text":"Reading invalid books always errors is table","Labels":[],"Nodes":[{"Name":"Entry","Text":"Empty book","Labels":[],"Nodes":[],"InnerParentContainer":false,"LineSpaceLevel":0},{"Name":"Entry","Text":"Only title","Labels":[],"Nodes":[],"InnerParentContainer":false,"LineSpaceLevel":0},{"Name":"Entry","Text":"Only author","Labels":[],"Nodes":[],"InnerParentContainer":false,"LineSpaceLevel":0},{"Name":"Entry","Text":"Missing pages","Labels":[],"Nodes":[],"InnerParentContainer":false,"LineSpaceLevel":0}],"InnerParentContainer":true,"LineSpaceLevel":0}],"InnerParentContainer":false,"LineSpaceLevel":0}] 
   267  
   268  ``` 
   269  
   270  ### Printing a text outline of an existing text outline file
   271   This will generate the outline and output to your terminal. This would only be useful for troubleshooting purposes. i.e. To make sure complex text outlines are graphed properly in the tree.
   272  
   273  `./mage PrintOutlineOfTextSpec <path>/<to>/<outline-file>`
   274  
   275  ```bash
   276  $ ./mage PrintOutlineOfTextSpec /tmp/outlines/books.outline
   277  I0622 22:32:34.429681   23787 testcasemapper.go:58] Mapping outline from a text file, /tmp/outlines/books.outline
   278  I0622 22:32:34.429771   23787 testcasemapper.go:40] Printing outline:
   279  
   280  BookSuiteDescribe: Book service E2E tests
   281    Describe: Categorizing book length   @book
   282      When: the book has more than 300 pages   @slow
   283        It: Should be a novel
   284      When: the book has fewer than 300 pages   @fast
   285        It: should be a short story
   286    Describe: Creating bookmarks in a book   @book, @bookmark, @parallel
   287      It: Has no bookmarks by default
   288      It: Can add bookmarks
   289    DescribeTable: Reading invalid books always errors is table
   290      Entry: Empty book
   291      Entry: Only title
   292      Entry: Only author
   293      Entry: Missing pages
   294  
   295  ``` 
   296  
   297  ### Updating the pkg framework describe file
   298  
   299  Once you are comfortable with your test you can update the framework/describe.go in our package directory.
   300  
   301  `./mage AppendFrameworkDescribeGoFile tests/<test-package>/<specfile>.go`
   302  
   303  ```bash
   304  $ ./mage AppendFrameworkDescribeGoFile tests/books/books.go
   305  I0623 11:56:42.997793   20862 magefile.go:670] Inspecting Ginkgo spec file, tests/books/books.go
   306  pkg/framework/describe.go
   307  
   308  ```
   309  
   310   ### Generating Ginkgo Test Suite File
   311  
   312   This command will help setup a test suite file within the `cmd/` directory. It will do the test package import based on the name of the package you passed in. So using the example below it will assume there is a `tests/chaos` package to import as well. It uses a simplified version of the `cmd/e2e_test.go` as a template to allow you to leverage the existing functionality built into the framework like webhooks eventing. Edit this file as you feel necessary.
   313  
   314  NOTE: You may not need to generate this file. This is useful when you want to move a type of testing into a separate suite that wouldn't go into the existing e2e test suite package. i.e. chaos testing. We have a current example with the existing `cmd/loadsTest.go` which are used to run the AppStudio Load tests.
   315  
   316  `./mage GenerateTestSuiteFile <name of test package under tests directory>`
   317  
   318   ```bash
   319  $ ./mage GenerateTestSuiteFile chaos
   320  I0623 12:48:13.761038   31196 magefile.go:467] Creating new test suite file cmd/chaos_test.go.
   321  cmd/chaos_test.go
   322  
   323  ```