{"id":43241106,"url":"https://github.com/levinine/functional-tests","last_synced_at":"2026-02-01T11:37:30.093Z","repository":{"id":42524232,"uuid":"431887415","full_name":"levinine/functional-tests","owner":"levinine","description":"Java-based Cucumber Test Automation Framework for UI and REST API Testing","archived":false,"fork":false,"pushed_at":"2026-01-26T22:01:26.000Z","size":76962,"stargazers_count":1,"open_issues_count":9,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-27T09:30:13.858Z","etag":null,"topics":["allure","assertj","cucumber","java","junit","junit4","openapi","openapi-generator","rest-assured","restassured","selenium"],"latest_commit_sha":null,"homepage":"https://levinine.github.io/functional-tests/","language":"Java","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/levinine.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-11-25T15:09:49.000Z","updated_at":"2026-01-26T22:00:27.000Z","dependencies_parsed_at":"2025-12-29T11:07:40.140Z","dependency_job_id":"b59cfce1-4369-4df5-be9a-a7d9d85c43aa","html_url":"https://github.com/levinine/functional-tests","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/levinine/functional-tests","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/levinine%2Ffunctional-tests","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/levinine%2Ffunctional-tests/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/levinine%2Ffunctional-tests/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/levinine%2Ffunctional-tests/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/levinine","download_url":"https://codeload.github.com/levinine/functional-tests/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/levinine%2Ffunctional-tests/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28977330,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T11:31:13.034Z","status":"ssl_error","status_checked_at":"2026-02-01T11:30:25.558Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["allure","assertj","cucumber","java","junit","junit4","openapi","openapi-generator","rest-assured","restassured","selenium"],"created_at":"2026-02-01T11:37:29.221Z","updated_at":"2026-02-01T11:37:30.079Z","avatar_url":"https://github.com/levinine.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Levi9 functional-tests\r\n\r\n## Used Technologies\r\n\r\n- [Java](https://www.java.com/)\r\n- [JUnit 4](https://junit.org/junit4/)\r\n- [AssertJ](http://joel-costigliola.github.io/assertj/)\r\n- [Cucumber](https://docs.cucumber.io/)\r\n- [Project Lombok](https://projectlombok.org/)\r\n- [REST-Assured](https://github.com/rest-assured/rest-assured/wiki/Usage)\r\n- [Awaitility](https://github.com/awaitility/awaitility/wiki/Usage)\r\n- [Selenium](https://www.seleniumhq.org/)\r\n- [Logback](https://logback.qos.ch/)\r\n- [OpenAPI](https://www.openapis.org/)\r\n\r\n## Local Development Setup\r\n\r\n### Download and install\r\n\r\n- [Java 21+](http://www.oracle.com/technetwork/java/javase/downloads/index.html) and installed as\r\n  described [here](https://docs.oracle.com/en/java/javase/21/install/overview-jdk-installation.html)\r\n- [Maven 3.9+](https://maven.apache.org/download.cgi) and installed as described [here](https://maven.apache.org/install.html)\r\n- IDE of choice, [IntelliJ IDEA](https://www.jetbrains.com/idea/download) or [Eclipse](https://www.eclipse.org/downloads/)\r\n- [Lombok](https://projectlombok.org/download) and configured on chosen IDE, [IntelliJ IDEA](https://projectlombok.org/setup/intellij)\r\n  or [Eclipse](https://projectlombok.org/setup/eclipse)\r\n- Cucumber plug-ins for chosen IDE, [IntelliJ IDEA Cucumber for Java plug-in](https://plugins.jetbrains.com/plugin/7212-cucumber-for-java)\r\n  or [Cucumber Eclipse plug-in](https://cucumber.github.io/cucumber-eclipse/)\r\n    - More information about Cucumber Plug-ins usage\r\n        - [IntelliJ IDEA Cucumber for Java plug-in](https://www.jetbrains.com/help/idea/cucumber-support.html)\r\n        - [Cucumber Eclipse plug-in](https://github.com/cucumber/cucumber-eclipse/blob/master/README.md)\r\n- [IntelliJ IDEA Save Actions plug-in](https://plugins.jetbrains.com/plugin/22113-save-actions--xdev-edition) to apply code formatting on save\r\n  action (this is not needed for Eclipse as it comes built-in)\r\n- SonarLint plug-in for chosen IDE [IntelliJ IDEA SonarLint plug-in](https://plugins.jetbrains.com/plugin/7973-sonarlint)\r\n  or [Eclipse SonarLint plug-in](https://marketplace.eclipse.org/content/sonarlint)\r\n\r\n## Project usage\r\n\r\nInstall all dependencies:\r\n\r\n```console\r\nmvn clean install -DskipTests -DskipReports\r\n```\r\n\r\nGenerate OpenAPI models by compiling project (even though `install` also compiles project. it will do it only if it detects changes):\r\n\r\n```console\r\nmvn clean compile\r\n```\r\n\r\nTests are executed by running `verify` command in project folder:\r\n\r\n```console \r\nmvn clean verify\r\n```\r\n\r\nAdditional parameters:\r\n\r\n- `-Denv` - Environment on which to execute tests i.e ```-Denv=local```, if not specified `development` will be used.\r\n- `-Dtags` - Scenario tags to execute or not to execute. If not specified sanity tests will be executed excluding skipped scenarios and scenarios with\r\n  known bugs, i.e. ```(@sanity) and (not @skip or not @bug)```. Tag expression is an infix boolean expression, and there can be one or multiple tags,\r\n  some examples:\r\n    - `@sanity` - Scenarios tagged with `@sanity` will be executed\r\n    - `@management and not @room-management` - Scenarios tagged with `@management` that are not also tagged with `@room-management` will be executed\r\n    - `@management and @room-management` - Scenarios tagged with both `@management` and `@room-management` will be executed\r\n    - `@booking or @contact` - Scenarios tagged with either `@booking` or `@contact` will be executed\r\n    - `(@booking or @contact) and (not @bug)` - Scenarios tagged with either `@booking` or `@contact` that are not also tagged with `@bug` will be\r\n      executed\r\n- `-Dremote` - Defines if execution is done locally or remotely i.e. ```-Dremote=false``` execute using local browsers and drivers\r\n  or ```-Dremote=true``` execute remotely using Selenium Grid. If set to true, `-DremoteUrl` must be set also.\r\n- `-DremoteUrl` - URL of Selenium Grid which is used for remote execution of Selenium Tests.\r\n- `-Dbrowser` - Browser on which UI test will be used i.e. ```-Dbrowser=firefox```, if not specified `chrome` will be used. Possible values are:\r\n    - `chrome`\r\n    - `firefox`\r\n- `-Dheadless` - Defines if execution is done with Browsers running in headless mode or not.\r\n- `-DparallelCount` - Maximum number of scenarios executed in parallel i.e. ```-DparallelCount=5```, if not specified `3` will be used.\r\n\r\nFor example to execute @ui and @api tests, excluding skipped and scenarios with known issues, with 5 features in parallel one development environment\r\nwith Chrome browser running in headless mode and not using remote Selenium Grid, command will look like:\r\n\r\n```console \r\nmvn clean verify -Dtags='(@ui or @api) and (not @skip and not @bug)' -DparallelCount=5 -Denv=development -Dbrowser=chrome -Dheadless -Dremote=false\r\n```\r\n\r\n### OpenAPI Specification\r\n\r\nThis project uses OpenAPI Specification which enables generation of API client libraries, server stubs, and documentation from an OpenAPI\r\nSpecification (formerly known as Swagger). This tool aims to streamline the development process by automating the generation of boilerplate code and\r\npromoting consistency between the API definition and the actual implementation.\r\n\r\nFor Maven users, the OpenAPI Generator provides a Maven plugin that integrates seamlessly into the build process. The plugin allows developers to\r\ngenerate API client libraries, server stubs, and documentation directly from the OpenAPI Specification during the Maven build lifecycle. This\r\nintegration simplifies the workflow for projects using Maven, as code generation can be triggered automatically as part of the build process.\r\n\r\nUsage of the OpenAPI Generator Maven plugin, is configured within the project's pom.xml file. There is specified the OpenAPI Specification\r\nfiles location and other relevant options to customize the generated code. When the Maven build is executed, the plugin fetches the OpenAPI\r\nSpecifications and generates the desired artifacts, such as client libraries or server stubs, according to the specified configuration.\r\n\r\nTo make it work in IDEs, like IntelliJ IDEA, make sure to add `Target` folder as `Generated Sources Root`. To do that in IntelliJ IDEA, after\r\nexecuting `mvn clean compile` command, `Target` folder will be created. After that just right click on it, and select `Mark Directory as` option and\r\nchoose `Generated Sources Root`.\r\n\r\nOverall, the OpenAPI Generator Maven plugin enhances the development experience for Maven-based projects by automating the generation of API-related\r\ncode and ensuring that the codebase stays in sync with the API specification.\r\n\r\n## Local Environment Setup\r\n\r\n### Docker (Docker for Desktop / Minikube)\r\n\r\n\u003e Before you proceed, you should install Docker Desktop depending on your OS and start it:\r\n\u003e\r\n\u003e- [Docker Desktop for Windows](https://docs.docker.com/desktop/install/windows-install/)\r\n\u003e- [Docker Desktop for Mac](https://docs.docker.com/desktop/install/mac-install/)\r\n\u003e\r\n\u003eAs Docker for Desktop is **paid** software now, instead of it you can set up and start minikube using bellow guides:\r\n\u003e\r\n\u003e- [Minikube Setup for Windows](/docs/minikube-setup-windows.md)\r\n\u003e- [Minikube Setup for Mac](/docs/minikube-setup-mac.md)\r\n\r\nAfter Docker has been installed on your machine, open the terminal inside `\u003clocal_path\u003e\\functional-tests` and use the following command:\r\n\r\n    docker compose -f ./docker-compose-restful-booker.yml up -d \r\n\r\nThat will start Restful Booker Platform locally.\r\n\r\nAfter everything is up and running you will have Restful Booker Platform available at:\r\n\r\n- Docker for Desktop: `http://localhost`\r\n- minikube: `http://kube.local`\r\n\r\n## Kubernetes (Minikube)\r\n\r\n\u003e Before you proceed, you should set up and start minikube using bellow guides:\r\n\u003e\r\n\u003e- [Minikube Setup for Windows](/docs/minikube-setup-windows.md)\r\n\u003e- [Minikube Setup for Mac](/docs/minikube-setup-mac.md)\r\n\r\nAfter minikube has been properly installed and started on your machine, open the terminal inside `\u003clocal_path\u003e\\functional-tests` and use the\r\nfollowing command:\r\n\r\n    kubectl apply -f .kube/restful-booker-platform.yml \r\n\r\nThat will start Restful Booker Platform locally.\r\n\r\nAfter everything is up and running you will have Restful Booker Platform available at `http://kube.local`.\r\n\r\n## Codding standards and rules\r\n\r\n### Coding Standards\r\n\r\n- To have all coding standards and formatting just import settings file into chosen IDE\r\n- IntelliJ\r\n    - Go to `File \u003e Settings \u003e Editor \u003e Code Style` and import code formatter `codestyle/intellij/Code Style.xml`\r\n    - Go to `File \u003e Settings \u003e Editor \u003e File and Code Templates` select `Includes` tab and configure it as displayed\r\n      on `codestyle/intellij/File and Code Templates - Includes - File Header example.PNG` and replace author data with your name and email\r\n    - Go to `File \u003e Settings \u003e Other Settings \u003e Save Actions` and configure it as displayed on `codestyle/intellij/Save Actions plugin.PNG`\r\n- Eclipse\r\n    - Go to `Window \u003e Preferences \u003e Java \u003e Code Style \u003e Formatter` and import `codestyle/eclipse/formatter.xml`\r\n    - Go to `Window \u003e Preferences \u003e Java \u003e Code Style \u003e Code Templates` and import `codestyle/eclipse/codetemplates.xml`\r\n        - After import is done expand `Comments \u003e Types` and replace author data with your name and email\r\n    - Go to `Window \u003e Preferences \u003e Java \u003e Code Style \u003e Cleanup` and import `codestyle/eclipse/cleanup.xml`\r\n    - Go to `Window \u003e Preferences \u003e Java \u003e Code Style \u003e Organize Imports` and import `codestyle/eclipse/importorder.importorder`\r\n\r\n### Coding Rules\r\n\r\n- Always apply code formatting before committing code\r\n- Always fix all Sonar issues stated in Sonar analysis of IDE before committing code\r\n- All Java Classes must have author data\r\n- String placeholder in log messages and exceptions is `{}` where in assert messages is `%s`\r\n  Test data is passed between tests using `Storage`\r\n    - `Storage` is comprised of lists with domain entity objects (Pets, Orders, etc.)\r\n    - When creating new entity object make sure that it represent functional domain entity\r\n    - When creating new entity object use only builders as way to create those objects, not constructors\r\n    - Extending existing entities is encouraged when additional data for them is needed, but it must make sure that new fields are updated accordingly\r\n      in steps\r\n    - When working with Storage, always if otherwise not needed, use latest stored values for entity you need\r\n- When testing some asynchronous operation test must wait for some condition to be fulfilled, **NEVER** for some predefined time.\r\n    - To implement conditional waits Awaitility is used in one of its formats.\r\n        - If asynchronous wait is not part of some assert, plane Java 8 implementation with lambda should be used, more on that is\r\n          available [here](https://github.com/awaitility/awaitility/wiki/Usage#example-7---java-8)\r\n        - If asynchronous wait is for some assert, AssertJ implementation of Awaitility should be used, more on that is\r\n          available [here](https://github.com/awaitility/awaitility/wiki/Usage#example-8---using-assertj-or-fest-assert)\r\n- When adding new application properties value *ALWAYS* make sure that it is added for all environment application properties\r\n\r\n### Developing new tests\r\n\r\nGeneral rules when creating test data for some test in order of priority:\r\n\r\n1. Create data over REST API calls\r\n2. Create data over Database Queries\r\n3. Create data over UI interface\r\n\r\nAlways first tend to create test data with REST API calls, only if that way is not possible than try other two ways in order mentioned above.\r\n\r\nWhen developing new automated test have in mind next order:\r\n\r\n1. Create REST API test\r\n2. Create UI tests\r\n\r\nAlways make sure that test is developed in most optimized way for fast and reliable execution, meaning that only if not possible to develop test as\r\nREST API call than develop it as UI test, which are slower and much more prone to errors.\r\n\r\n### REST API Interface\r\n\r\nTo add new Rest API calls to App back end next steps must be followed:\r\n\r\n1. Create Service class for that domain of App in `rest/service/{servicename}` where all REST calls to that endpoint will be located\r\n2. Data Source (Transfer) Objects must be created in `rest/data` package\r\n3. Call created Service class from step definitions\r\n\r\nTo add new communication interface with any of microservices next steps must be followed:\r\n\r\n1. (optionally) Add Microservice API dependency in `pom.xml` with parametrized version\r\n2. Create new REST Client class in `rest/client` package for that microservice, by extending BaseRestClient\r\n3. Add micro-service URL to all `application-[environment].properties` files\r\n4. Create Service Class in `rest/service/{servicename}` package to Communicate with service\r\n    - All direct communication with Microservice should be done in Service classes which are called from step definitions\r\n5. Adding Data Source (Transfer) Objects is needed for proper Serialization and Deserialization of payloads, however if Microservice API dependency is\r\n   added to `pom.xml`, than they are not needed\r\n6. Call created Service class from step definitions\r\n\r\n### UI Interface\r\n\r\nTo add new UI interface, Page Object pattern is used, meaning that for each application page, a Page Object class which represents it must exist in\r\nTest Automation framework.\r\nTo automate actions on some new page:\r\n\r\n1. Create Page Object(s) for it in `com.levi9.functionaltests.ui.pages` (it can also be multiple page objects if page is complex)\r\n    - Order of priority for Selenium selectors is:\r\n        1. ID locator\r\n        2. CSS locator\r\n        3. Name locator\r\n        4. Link locator\r\n        5. XPath locator\r\n2. Call its methods from step definitions\r\n\r\n## Gherkin standards and rules\r\n\r\n### Describing Features\r\n\r\nEvery feature must only contain scenarios related to that it. When grouping scenarios under one feature make sure that `@Background` for that feature\r\nis common for all scenarios.\r\nIf some feature is complex and there are different `@Background` for group them in multiple feature file.\r\n\r\nIf you have problems describing feature you can use next template, known as a Feature Injection template:\r\n\r\n\tIn order to \u003cmeet some goal\u003e\r\n\tAs a \u003ctype of stakeholder\u003e\r\n\tI want \u003ca feature\u003e\r\n\r\nBy starting with the goal or value that the feature provides, you’re making it explicit to everyone who ever works on this feature why they’re giving\r\nup their precious time. You’re also offering people an opportunity to think about other ways that the goal could be met.\r\n\r\n### Writing Scenarios\r\n\r\nUsing Given-When-Then in sequence is a great reminder for several great test design ideas. It suggests that pre-conditions and post-conditions need to\r\nbe identified and separated. It suggests that the purpose of the test should be clearly communicated, and that each scenario should check one and only\r\none thing. When there is only one action under test, people are forced to look beyond the mechanics of test execution and really identify a clear\r\npurpose.\r\n\r\nWhen used correctly, Given-When-Then helps teams design specifications and checks that are easy to understand and maintain. As tests will be focused\r\non one particular action, they will be less brittle and easier to diagnose and troubleshoot. When the parameters and expectations are clearly\r\nseparated, it’s easier to evaluate if we need to add more examples, and discover missing cases.\r\n\r\n#### General Rules\r\n\r\nTo prevents most of accidental misuse of Given-When-Then use:\r\n\r\n- Write *Given* in Past tense as Passive sentences - these statements are describing preconditions and parameters (values rather than actions)\r\n- Write *When* in Present tense as Active sentences - these statements are describing action under test\r\n- Write *Then* in Future tense as Passive sentences - these statements are describing post-conditions and expectations (values rather than actions)\r\n\r\nMake sure that there is only **one** *When* statement for each scenario.\r\n\r\nAlso make sure that there are no **and** conjunctions in sentences. If there is, it must be split into separate step.\r\n\r\n### Matching Step Definition\r\n\r\n- To match Gherkin Scenario Step text both **_Regular Expressions_** and **_Cucumber Expression_** are used\r\n- When writing **_Regular Expressions_** matchers always make sure that at least similar words and plurals are covered and will be matched\r\n    - Tool which can help you write and match regular expression [Regexr](https://regexr.com/)\r\n- When writing **_Cucumber Expressions_** matchers always make sure that at least similar words and plurals are covered and will be matched by using:\r\n    - [Optional text](https://github.com/cucumber/cucumber-expressions#optional-text)\r\n    - [Alternative text](https://github.com/cucumber/cucumber-expressions#alternative-text)\r\n    - [Escaping](https://github.com/cucumber/cucumber-expressions#escaping)\r\n\r\n## Execute Functional Tests using GitHub Actions Workflows on GitHub\r\n\r\nAll GitHub Actions Workflows are configured in [**GitHub Folder**](/.github/workflows) yaml files.\r\n\r\nThey all can be found by navigating to [GitHub Repository \u003e Actions](https://github.com/levinine/functional-tests/actions).\r\n\r\n![GitHub Actions Workflows](/docs/imgs/GitHub-Actions.png)\r\n\r\nThere are 2 GitHub Actions Workflows setup for Functional Tests repository:\r\n\r\n- [Functional Tests](https://github.com/levinine/functional-tests/actions/workflows/functional-tests.yml)\r\n- [Sanity Check](https://github.com/levinine/functional-tests/actions/workflows/sanity-check.yml)\r\n\r\n### Functional Tests\r\n\r\nThis GitHub Action Workflow Executes All Functional Tests on `local` environment using `chrome` and `firefox` browsers from defined\r\nbranch (by default it is `main`).\r\nEnvironment `local` means that, Restful Booker Platform will be started inside GitHub Services and tests will run against it.\r\n\r\nGitHub Action Workflow configuration file of this workflow is [functional-tests.yml](/.github/workflows/functional-tests.yml).\r\n\r\nThis workflow is only triggered Manually. Steps to trigger it:\r\n\r\n1. Open [Functional Tests](https://github.com/levinine/functional-tests/actions/workflows/functional-tests.yml)\r\n2. Click on `Run workflow` button\r\n    - (which opens sub-modal where `Branch` can be selected, `main` selected by default)\r\n3. Select `Branch`\r\n4. Click on `Run workflow` button\r\n\r\n![Functional Tests](/docs/imgs/Functional-Tests.png)\r\n\r\nAlso, on [Functional Tests](https://github.com/levinine/functional-tests/actions/workflows/functional-tests.yml) page, status of all ongoing and\r\npreviously executed 'Functional Tests' Workflow runs can be found.\r\n\r\nLatest Test reports, with trends history, Functional Tests GitHub Action Workflow can be\r\nfound [here](https://levinine.github.io/functional-tests/).\r\n\r\n![Functional Tests Reports](/docs/imgs/Functional-Tests-Reports.png)\r\n\r\nThere are 3 types of reports:\r\n\r\n1. Allure Report, with trend history\r\n2. Latest Cluecumber Report, without trend history\r\n3. Latest Cucumber Report, without trend history\r\n\r\n### Sanity Check\r\n\r\nThis GitHub Action Workflow Executes `@sanity` tagged tests of Functional Tests on `local` environment using `chrome` and `firefox`.\r\nbrowsers from `main` or Pull Request source branch.\r\n\r\nGitHub Action Workflow configuration file of this workflow is [sanity-check.yml](/.github/workflows/sanity-check.yml).\r\n\r\nThis workflow is only triggered automatically on specific events:\r\n\r\n- Merge Events on `main` branch\r\n- Create / Update GitHub Pull Request Events\r\n\r\nAlso, on [Sanity Check](https://github.com/levinine/functional-tests/actions/workflows/sanity-check.yml) page, status of all ongoing and\r\npreviously executed 'Sanity Check' Workflow runs can be found.\r\n\r\nThis workflow doesn't produce reports like Functional Tests Workflow, and its status and results can be checked inside GitHub Action Job Summary.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flevinine%2Ffunctional-tests","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flevinine%2Ffunctional-tests","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flevinine%2Ffunctional-tests/lists"}