├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature_reuqest.md │ ├── non--crash-security--bug.md │ └── other.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml ├── markdown_lint_config.json ├── pre-commit ├── release-drafter.yml ├── testing │ ├── core.yaml │ ├── grpc.yaml │ └── grpc_ref.yaml └── workflows │ ├── build.yaml │ ├── docs.yaml │ ├── issue-comment.yml │ ├── license-check.yaml │ ├── release-drafter.yml │ └── release.yaml ├── .gitignore ├── .gitpod.yml ├── .goreleaser.yaml ├── .licenserc.yaml ├── .remarkrc ├── .vscode └── extensions.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING-ZH.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README-ZH.md ├── README.md ├── SECURITY.md ├── action.yml ├── checklink_config.json ├── cmd ├── compose.go ├── convert.go ├── convert_test.go ├── data │ ├── favicon.ico │ ├── font │ │ └── .keep │ ├── image │ │ └── warn.jpg │ ├── index.css │ ├── index.html │ └── index.js ├── extension.go ├── extension_test.go ├── function.go ├── function_test.go ├── init.go ├── jsonschema.go ├── jsonschema_test.go ├── mock-compose.go ├── mock.go ├── mock_test.go ├── root.go ├── root_test.go ├── run.go ├── run_test.go ├── sample.go ├── sample_test.go ├── server.go ├── server_test.go ├── service.go └── testdata │ ├── invalid-api.yaml │ ├── invalid-schema.yaml │ ├── postman.json │ ├── simple-suite.yaml │ └── stores.yaml ├── console ├── atest-desktop │ ├── README.md │ ├── api-testing.icns │ ├── api-testing.ico │ ├── api-testing.png │ ├── api.js │ ├── api.test.js │ ├── forge.config.js │ ├── index.html │ ├── main.js │ ├── package-lock.json │ ├── package.json │ └── preload.js └── atest-ui │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── .prettierrc.json │ ├── .vscode │ └── extensions.json │ ├── README.md │ ├── cypress.config.ts │ ├── cypress │ ├── e2e │ │ ├── gRPC.cy.ts │ │ ├── http.cy.ts │ │ ├── tsconfig.json │ │ └── util.ts │ ├── fixtures │ │ └── example.json │ └── support │ │ ├── commands.ts │ │ └── e2e.ts │ ├── env.d.ts │ ├── gen.sh │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── public │ └── favicon.ico │ ├── src │ ├── App.vue │ ├── assets │ │ ├── base.css │ │ ├── logo.svg │ │ └── main.css │ ├── components │ │ ├── Button.vue │ │ ├── EditButton.vue │ │ ├── HistoryInput.vue │ │ ├── LoginDialog.vue │ │ ├── TestSuiteCreationDialog.vue │ │ └── TestSuiteImportDialog.vue │ ├── i18n.ts │ ├── locales │ │ ├── en.json │ │ └── zh.json │ ├── main.ts │ ├── theme.ts │ └── views │ │ ├── APIInput.vue │ │ ├── DataManager.vue │ │ ├── MockManager.vue │ │ ├── SecretManager.vue │ │ ├── StoreManager.vue │ │ ├── TemplateFunctions.vue │ │ ├── TestCase.vue │ │ ├── TestSuite.vue │ │ ├── TestingHistoryPanel.vue │ │ ├── TestingPanel.vue │ │ ├── WelcomePage.vue │ │ ├── __test__ │ │ ├── cache.spec.ts │ │ ├── common.ts │ │ ├── net.spec.ts │ │ ├── store.spec.ts │ │ └── types.spec.ts │ │ ├── cache.ts │ │ ├── magicKeys.ts │ │ ├── net-vue.ts │ │ ├── net.ts │ │ ├── store.ts │ │ └── types.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.node.json │ ├── tsconfig.vitest.json │ ├── ui.go │ ├── vite.config.ts │ └── vitest.config.ts ├── docs ├── README.md ├── api-testing-mock-schema.json ├── api-testing-schema.json ├── constants.go ├── manifests │ ├── argocd │ │ └── simple.yaml │ ├── docker-compose.yml │ ├── kubernetes │ │ ├── default │ │ │ ├── kustomization.yaml │ │ │ └── manifest.yaml │ │ └── docker.io │ │ │ └── kustomization.yaml │ └── podman.yaml ├── package-lock.json └── site │ ├── .dockerignore │ ├── .gitignore │ ├── .nvmrc │ ├── Dockerfile │ ├── assets │ ├── atest-vscode.png │ ├── icons │ │ ├── logo.png │ │ └── logo.svg │ └── scss │ │ └── _variables_project.scss │ ├── config.yaml │ ├── content │ ├── en │ │ ├── _index.md │ │ ├── about │ │ │ └── index.md │ │ ├── contributions │ │ │ ├── CODE_OF_CONDUCT.md │ │ │ ├── CONTRIBUTING.md │ │ │ ├── SECURITY.md │ │ │ ├── _index.md │ │ │ ├── design │ │ │ │ ├── Todo.md │ │ │ │ └── _index.md │ │ │ └── roadmap.md │ │ ├── latest │ │ │ ├── _index.md │ │ │ ├── api │ │ │ │ ├── _index.md │ │ │ │ └── extension_types.md │ │ │ ├── install │ │ │ │ ├── _index.md │ │ │ │ └── install-locally.md │ │ │ ├── releases │ │ │ │ ├── _index.md │ │ │ │ └── v0.1.0.md │ │ │ └── tasks │ │ │ │ ├── _index.md │ │ │ │ ├── grpc-manual.md │ │ │ │ ├── mock-server.md │ │ │ │ ├── prometheus.md │ │ │ │ ├── quickstart.md │ │ │ │ └── secure.md │ │ ├── news │ │ │ ├── _index.md │ │ │ ├── blogs │ │ │ │ └── _index.md │ │ │ ├── presentations │ │ │ │ └── _index.md │ │ │ └── releases │ │ │ │ └── _index.md │ │ └── search.md │ └── zh │ │ ├── _index.md │ │ ├── about │ │ └── index.md │ │ ├── contributions │ │ ├── CONTRIBUTING-ZH.md │ │ ├── _index.md │ │ ├── design │ │ │ ├── Goals.md │ │ │ ├── _index.md │ │ │ └── security-policy.md │ │ └── roadmap.md │ │ ├── latest │ │ ├── _index.md │ │ ├── api │ │ │ ├── _index.md │ │ │ └── extension_types.md │ │ ├── install │ │ │ ├── _index.md │ │ │ ├── install-helm.md │ │ │ └── install-local.md │ │ └── tasks │ │ │ ├── _index.md │ │ │ ├── code-generator.md │ │ │ ├── e2e.md │ │ │ ├── extension.md │ │ │ ├── grpc-TLS.md │ │ │ ├── grpc-manual.md │ │ │ ├── job.md │ │ │ ├── mock.md │ │ │ ├── mock │ │ │ ├── image-registry.yaml │ │ │ ├── object.yaml │ │ │ └── simple.yaml │ │ │ ├── quickstart.md │ │ │ ├── secure.md │ │ │ ├── template.md │ │ │ ├── testsuite.yaml │ │ │ └── verify.md │ │ ├── news │ │ ├── _index.md │ │ ├── blogs │ │ │ ├── _index.md │ │ │ └── glcc-2023-announce.md │ │ ├── presentations │ │ │ └── _index.md │ │ └── releases │ │ │ └── _index.md │ │ ├── releases │ │ ├── _index.md │ │ ├── release-note-v0.0.12.md │ │ ├── release-note-v0.0.13.md │ │ ├── release-note-v0.0.14.md │ │ ├── release-note-v0.0.15.md │ │ ├── release-note-v0.0.17.md │ │ └── release-note-v0.0.18.md │ │ └── search.md │ ├── data │ └── adopters.yaml │ ├── docker-compose.yaml │ ├── go.mod │ ├── go.sum │ ├── hugo.toml │ ├── layouts │ ├── 404.html │ └── shortcodes │ │ └── adopters.html │ ├── package.json │ └── static │ ├── favicons │ ├── favicons.ico │ └── site.webmanifest │ ├── img │ └── logo.png │ └── logos │ ├── airspacelink.svg │ └── logo.png ├── e2e ├── Dockerfile ├── README.md ├── code-generator │ ├── Dockerfile │ ├── JavaScript.sh │ ├── compose.yaml │ ├── curl.sh │ ├── entrypoint.sh │ ├── golang.sh │ ├── java.sh │ ├── python.sh │ ├── robot-framework.sh │ ├── start.sh │ └── test-suites │ │ └── test-suite.yaml ├── compose-external.yaml ├── compose-k8s.yaml ├── compose.yaml ├── entrypoint.sh ├── git.yaml ├── k8s.sh ├── openssl.cnf ├── start.sh └── test-suite-common.yaml ├── extensions └── README.md ├── go.mod ├── go.sum ├── helm └── api-testing │ ├── .helmignore │ ├── Chart.lock │ ├── Chart.yaml │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── pvc.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ ├── servicemonitor.yaml │ └── tests │ │ └── test-connection.yaml │ └── values.yaml ├── main.go ├── pkg ├── apispec │ ├── data │ │ └── proto │ │ │ ├── google │ │ │ ├── api │ │ │ │ ├── annotations.proto │ │ │ │ └── http.proto │ │ │ └── protobuf │ │ │ │ ├── annotations.proto │ │ │ │ ├── any.proto │ │ │ │ ├── descriptor.proto │ │ │ │ ├── duration.proto │ │ │ │ ├── struct.proto │ │ │ │ └── timestamp.proto │ │ │ ├── protoc-gen-openapiv2 │ │ │ └── options │ │ │ │ ├── annotations.proto │ │ │ │ └── openapiv2.proto │ │ │ └── validate │ │ │ └── validate.proto │ ├── fake.go │ ├── fake_test.go │ ├── grpc.go │ ├── grpc_test.go │ ├── remote_swagger.go │ ├── swagger.go │ ├── swagger_test.go │ └── testdata │ │ └── swagger.json ├── compare │ ├── compare.go │ ├── compare_test.go │ ├── error.go │ └── error_test.go ├── downloader │ ├── extension.go │ ├── oci.go │ ├── oci_test.go │ ├── progress.go │ └── testdata │ │ └── registry.yaml ├── extension │ ├── option.go │ ├── option_test.go │ ├── pprof.go │ ├── signal.go │ └── singal_test.go ├── generator │ ├── code_generator.go │ ├── code_generator_test.go │ ├── converter_jmeter.go │ ├── converter_jmeter_test.go │ ├── converter_raw.go │ ├── converter_raw_test.go │ ├── curl_generator.go │ ├── curl_generator_test.go │ ├── data │ │ ├── curl.tpl │ │ ├── main.go.tpl │ │ ├── main.java.tpl │ │ ├── main.javascript.tpl │ │ ├── main.python.tpl │ │ ├── robot-suite.tpl │ │ └── robot.tpl │ ├── golang_generator.go │ ├── helper.go │ ├── importer.go │ ├── importer_native.go │ ├── importer_native_test.go │ ├── importer_test.go │ ├── java_generator.go │ ├── javascript_generator.go │ ├── payload_generator.go │ ├── payload_generator_test.go │ ├── python_generator.go │ ├── robot_generator.go │ ├── robot_generator_test.go │ └── testdata │ │ ├── expected_go_body_request_code.txt │ │ ├── expected_go_code.txt │ │ ├── expected_go_cookie_request_code.txt │ │ ├── expected_go_form_request_code.txt │ │ ├── expected_java_code.txt │ │ ├── expected_java_cookie_request_code.txt │ │ ├── expected_java_form_request_code.txt │ │ ├── expected_javascript_body_request_code.txt │ │ ├── expected_javascript_code.txt │ │ ├── expected_javascript_cookie_request_code.txt │ │ ├── expected_javascript_form_request_code.txt │ │ ├── expected_jmeter.jmx │ │ ├── expected_python_code.txt │ │ ├── expected_python_cookie_request_code.txt │ │ ├── expected_python_form_request_code.txt │ │ ├── expected_suite_from_postman.yaml │ │ ├── expected_suite_from_sub_postman.yaml │ │ ├── expected_testsuite.yaml │ │ ├── native.json │ │ ├── postman-sub.json │ │ ├── postman.json │ │ ├── simple.robot │ │ ├── suite.robot │ │ ├── test.proto │ │ └── with-headers.robot ├── limit │ ├── limiter.go │ ├── limiter_long_test.go │ └── limiter_test.go ├── logging │ ├── log.go │ └── log_test.go ├── mock │ ├── in_memory.go │ ├── in_memory_test.go │ ├── metrics.go │ ├── reader.go │ ├── server.go │ ├── testdata │ │ └── api.yaml │ └── types.go ├── oauth │ ├── interceptor.go │ └── interceptor_test.go ├── render │ ├── data │ │ └── templateUsage.yaml │ ├── doc.go │ ├── image.go │ ├── image_test.go │ ├── local.go │ ├── local_test.go │ ├── pdf.go │ ├── pdf_test.go │ ├── secret.go │ ├── template.go │ ├── template_test.go │ ├── zip.go │ └── zip_test.go ├── runner │ ├── data │ │ ├── html.html │ │ └── report.md │ ├── doc.go │ ├── expr_function.go │ ├── expr_function_test.go │ ├── graphql.go │ ├── graphql_test.go │ ├── grpc.go │ ├── grpc_test.go │ ├── grpc_test │ │ ├── server.go │ │ ├── test.pb │ │ ├── test.pb.go │ │ ├── test.proto │ │ ├── test_grpc.pb.go │ │ └── testassets │ │ │ ├── server.key │ │ │ └── server.pem │ ├── http.go │ ├── http_reverse.go │ ├── http_reverse_test.go │ ├── http_test.go │ ├── kubernetes │ │ ├── client.go │ │ ├── client_test.go │ │ ├── doc.go │ │ ├── verify.go │ │ └── verify_test.go │ ├── logger.go │ ├── monitor │ │ ├── dumy_monitor.go │ │ ├── monitor.pb.go │ │ ├── monitor.proto │ │ └── monitor_grpc.pb.go │ ├── reporter.go │ ├── reporter_discard.go │ ├── reporter_discard_test.go │ ├── reporter_memory.go │ ├── reporter_memory_test.go │ ├── reporter_prometheus.go │ ├── reporter_prometheus_test.go │ ├── runner.go │ ├── runner_factory.go │ ├── runner_test.go │ ├── testdata │ │ ├── generic_response.json │ │ ├── json-result.json │ │ ├── report.html │ │ └── swagger.json │ ├── verify.go │ ├── verify_test.go │ ├── writer.go │ ├── writer_github_pr_comment.go │ ├── writer_github_pr_comment_test.go │ ├── writer_grpc.go │ ├── writer_grpc_test.go │ ├── writer_html.go │ ├── writer_html_test.go │ ├── writer_http.go │ ├── writer_http_test.go │ ├── writer_json.go │ ├── writer_json_test.go │ ├── writer_markdown.go │ ├── writer_markdown_test.go │ ├── writer_pdf.go │ ├── writer_pdf_test.go │ ├── writer_std.go │ ├── writer_std_test.go │ └── writer_templates │ │ ├── example.tpl │ │ ├── server.go │ │ ├── writer.pb.go │ │ ├── writer.proto │ │ └── writer_grpc.pb.go ├── secret │ └── types.go ├── server │ ├── constant.go │ ├── convert.go │ ├── convert_test.go │ ├── data │ │ └── headers.yaml │ ├── fake.yaml │ ├── fake_server.go │ ├── gateway.go │ ├── gateway_test.go │ ├── http.go │ ├── http_test.go │ ├── proto.go │ ├── proto_test.go │ ├── remote_runner.go │ ├── remote_server.go │ ├── remote_server_test.go │ ├── server.pb.go │ ├── server.pb.gw.go │ ├── server.proto │ ├── server.swagger.json │ ├── server_grpc.pb.go │ ├── server_grpc_test.go │ ├── store_ext_manager.go │ ├── store_ext_manager_test.go │ └── testdata │ │ ├── postman.json │ │ ├── simple.yaml │ │ ├── simple_testcase.yaml │ │ └── swagger.json ├── service │ ├── runner.go │ └── sbom.go ├── testing │ ├── case.go │ ├── case_test.go │ ├── doc.go │ ├── loader.go │ ├── loader_file.go │ ├── loader_file_test.go │ ├── loader_non.go │ ├── loader_non_test.go │ ├── local │ │ ├── local_secret_service.go │ │ └── local_secret_service_test.go │ ├── parser.go │ ├── parser_test.go │ ├── remote │ │ ├── context.go │ │ ├── context_test.go │ │ ├── converter.go │ │ ├── converter_test.go │ │ ├── grpc_secret.go │ │ ├── grpc_secret_test.go │ │ ├── grpc_store.go │ │ ├── grpc_store_test.go │ │ ├── loader.pb.go │ │ ├── loader.proto │ │ └── loader_grpc.pb.go │ ├── store.go │ ├── store_test.go │ └── testdata │ │ ├── duplicated-names.yaml │ │ ├── generic_body.json │ │ ├── invalid-testcase.yaml │ │ ├── stores.yaml │ │ └── testcase.yaml ├── util │ ├── base64.go │ ├── default.go │ ├── default_test.go │ ├── error.go │ ├── error_test.go │ ├── expand.go │ ├── expand_test.go │ ├── grpc.go │ ├── grpc_test.go │ ├── home │ │ ├── common.go │ │ ├── common_test.go │ │ ├── darwin.go │ │ ├── doc.go │ │ ├── linux.go │ │ └── windows.go │ ├── http.go │ ├── http_test.go │ ├── map.go │ ├── map_test.go │ ├── net.go │ ├── path.go │ ├── path_test.go │ ├── rand.go │ ├── rand_test.go │ ├── slice.go │ ├── slice_test.go │ └── testdata │ │ ├── fuzz │ │ ├── FuzzEmptyThenDefault │ │ │ └── a5d1a2517d90f203 │ │ └── FuzzZeroThenDefault │ │ │ └── 26953e5f8daf8575 │ │ ├── report.html │ │ ├── test.proto │ │ └── test.zip └── version │ ├── constants.go │ ├── constants_test.go │ ├── mod.go │ ├── mod_test.go │ └── testdata │ └── go.mod.txt ├── qodana.yaml ├── sample ├── constants.go ├── grpc-sample.yaml ├── kubernetes.yaml ├── testsuite-gitee.yaml └── testsuite-gitlab.yaml ├── sonar-project.properties └── tools ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── SECURITY.md ├── github-actions └── setup-deps │ └── action.yml ├── linter ├── golangci-lint │ └── .golangci.yml └── yamlint │ └── .yamllint ├── make ├── common.mk ├── desktop.mk ├── docs.mk ├── env.mk ├── golang.mk ├── helm.mk ├── image.mk ├── lint.mk ├── proto.mk ├── run.mk ├── test.mk ├── tools.mk └── ui.mk └── src ├── golangci-lint ├── go.mod ├── go.sum └── pin.go └── yamllint └── requirements.txt /.dockerignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | extensions/ 3 | dist/ 4 | console/atest-desktop/ 5 | console/atest-ui/node_modules/ 6 | docs/site/node_modules/ 7 | docs/site/public/ 8 | docs/site/resources/ 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | charset = utf-8 11 | 12 | # 4 space indentation 13 | [*.{py,proto,go,js,ts,json,vue}] 14 | indent_style = space 15 | indent_size = 4 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.go text eol=lf 2 | *.vue text eol=lf 3 | *.js text eol=lf 4 | *.css text eol=lf 5 | *.html text eol=lf 6 | *.md text eol=lf 7 | *.yaml text eol=lf 8 | *.json text eol=lf 9 | *.yml text eol=lf 10 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # see also https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners 2 | # pkg/runner/grpc.go @Ink-33 3 | # pkg/runner/grpc_test.go @Ink-33 4 | # pkg/runner/verify.go @Ink-33 5 | 6 | tools/ @yuluo-yx 7 | docs/site @yuluo-yx 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: "Crash bug" 4 | url: https://github.com/LinuxSuRen/api-testing/SECURITY.md 5 | about: "Please file any crash bug with api-testing-security@googlegroups.com." 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_reuqest.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement,triage 6 | assignees: '' 7 | 8 | --- 9 | 10 | *Description*: 11 | >Describe the desired behavior, what scenario it enables and how it 12 | would be used. 13 | 14 | [optional *Relevant Links*:] 15 | >Any extra documentation required to understand the issue. 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/non--crash-security--bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug 3 | about: Bugs 4 | title: '' 5 | labels: bug,triage 6 | assignees: '' 7 | 8 | --- 9 | 10 | *Description*: 11 | >What issue is being seen? Describe what should be happening instead of 12 | the bug, for example: api-testing should not crash, the expected value isn't 13 | returned, etc. 14 | 15 | *Repro steps*: 16 | > Include sample requests, environment, etc. All data and inputs 17 | required to reproduce the bug. 18 | 19 | >**Note**: If there are privacy concerns, sanitize the data prior to 20 | sharing. 21 | 22 | *Environment*: 23 | >Include the environment like api-testing version, os version and so on. 24 | 25 | *Logs*: 26 | >Include the access logs and the api-testing logs. 27 | > 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/other.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Other 3 | about: Questions, design proposals, tech debt, etc. 4 | title: '' 5 | labels: triage 6 | assignees: '' 7 | 8 | --- 9 | 10 | *Description*: 11 | >Describe the issue. 12 | 13 | [optional *Relevant Links*:] 14 | >Any extra documentation required to understand the issue. 15 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | > We highly recommend you read [the contributor's documentation](https://github.com/LinuxSuRen/api-testing/blob/master/CONTRIBUTING.md) before starting the review process especially since this is your first contribution to this project. 8 | > 9 | > It was updated on 2024/5/27 10 | 11 | **What type of PR is this?** 12 | 21 | 22 | **What this PR does / why we need it**: 23 | 24 | **Which issue(s) this PR fixes**: 25 | 29 | Fixes # 30 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "gomod" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | - package-ecosystem: "npm" # See documentation for possible values 13 | directory: "/console/atest-ui" # Location of package manifests 14 | schedule: 15 | interval: "weekly" 16 | -------------------------------------------------------------------------------- /.github/markdown_lint_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD001": true, 3 | "MD002": false, 4 | "MD003": false, 5 | "MD004": false, 6 | "MD005": false, 7 | "MD006": false, 8 | "MD007": false, 9 | "MD008": false, 10 | "MD009": false, 11 | "MD010": false, 12 | "MD011": false, 13 | "MD012": false, 14 | "MD013": false, 15 | "MD014": false, 16 | "MD015": false, 17 | "MD016": false, 18 | "MD017": false, 19 | "MD018": false, 20 | "MD019": false, 21 | "MD020": false, 22 | "MD021": false, 23 | "MD022": false, 24 | "MD023": false, 25 | "MD024": false, 26 | "MD025": false, 27 | "MD026": false, 28 | "MD027": false, 29 | "MD028": false, 30 | "MD029": false, 31 | "MD030": false, 32 | "MD031": true, 33 | "MD032": false, 34 | "MD033": false, 35 | "MD034": false, 36 | "MD035": false, 37 | "MD036": false, 38 | "MD037": true, 39 | "MD038": true, 40 | "MD039": false, 41 | "MD040": false, 42 | "MD041": false, 43 | "MD042": false, 44 | "MD043": false, 45 | "MD044": false, 46 | "MD045": false, 47 | "MD046": false, 48 | "MD047": false, 49 | "MD048": false, 50 | "MD049": false, 51 | "MD050": false, 52 | "MD051": false 53 | } 54 | -------------------------------------------------------------------------------- /.github/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | make fmt test 4 | -------------------------------------------------------------------------------- /.github/testing/core.yaml: -------------------------------------------------------------------------------- 1 | #!api-testing 2 | # yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-schema.json 3 | name: atest 4 | api: | 5 | {{default "http://localhost:8080/api/v1" (env "SERVER")}} 6 | param: 7 | name: "{{randAlpha 6}}" 8 | items: 9 | - name: createSuite 10 | request: 11 | api: /suites 12 | method: POST 13 | body: | 14 | {"name": "{{.param.name}}"} 15 | -------------------------------------------------------------------------------- /.github/testing/grpc.yaml: -------------------------------------------------------------------------------- 1 | #!api-testing 2 | # yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-schema.json 3 | # see also https://github.com/LinuxSuRen/api-testing 4 | name: grpc-sample 5 | api: 127.0.0.1:7070 6 | spec: 7 | kind: grpc 8 | rpc: 9 | import: 10 | - ./pkg/server 11 | - ./pkg/apispec/data/proto 12 | protofile: server.proto 13 | items: 14 | - name: GetVersion 15 | request: 16 | api: /server.Runner/GetVersion 17 | - name: FunctionsQuery 18 | request: 19 | api: /server.Runner/FunctionsQuery 20 | body: | 21 | { 22 | "name": "hello" 23 | } 24 | expect: 25 | body: | 26 | { 27 | "data": [ 28 | { 29 | "key": "hello", 30 | "value": "func() string" 31 | } 32 | ] 33 | } 34 | - name: FunctionsQueryStream 35 | request: 36 | api: /server.Runner/FunctionsQueryStream 37 | body: | 38 | [ 39 | { 40 | "name": "hello" 41 | }, 42 | { 43 | "name": "title" 44 | } 45 | ] 46 | expect: 47 | verify: 48 | - "len(data) == 2" 49 | -------------------------------------------------------------------------------- /.github/testing/grpc_ref.yaml: -------------------------------------------------------------------------------- 1 | #!api-testing 2 | # yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-schema.json 3 | # see also https://github.com/LinuxSuRen/api-testing 4 | name: grpc-sample-reflection 5 | api: 127.0.0.1:7070 6 | spec: 7 | kind: grpc 8 | rpc: 9 | import: 10 | - ./pkg/apispec/data/proto 11 | serverReflection: true 12 | items: 13 | - name: GetVersion 14 | request: 15 | api: /server.Runner/GetVersion 16 | - name: FunctionsQuery 17 | request: 18 | api: /server.Runner/FunctionsQuery 19 | body: | 20 | { 21 | "name": "hello" 22 | } 23 | expect: 24 | body: | 25 | { 26 | "data": [ 27 | { 28 | "key": "hello", 29 | "value": "func() string" 30 | } 31 | ] 32 | } 33 | - name: FunctionsQueryStream 34 | request: 35 | api: /server.Runner/FunctionsQueryStream 36 | body: | 37 | [ 38 | { 39 | "name": "hello" 40 | }, 41 | { 42 | "name": "title" 43 | } 44 | ] 45 | expect: 46 | verify: 47 | - "len(data) == 2" 48 | -------------------------------------------------------------------------------- /.github/workflows/issue-comment.yml: -------------------------------------------------------------------------------- 1 | name: Issue and PR comment commands 2 | 3 | permissions: {} 4 | 5 | on: 6 | issue_comment: 7 | types: 8 | - created 9 | - edited 10 | 11 | jobs: 12 | execute: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | issues: write 16 | pull-requests: write 17 | steps: 18 | - uses: jpmcb/prow-github-actions@f4d01dd4b13f289014c23fe5a19878a2479cb35b # v1.1.3 19 | with: 20 | prow-commands: '/assign 21 | /unassign 22 | /area 23 | /kind 24 | /priority 25 | /remove 26 | /close 27 | /reopen 28 | /lock 29 | /milestone 30 | /hold 31 | /cc 32 | /uncc' 33 | github-token: "${{ secrets.GITHUB_TOKEN }}" 34 | -------------------------------------------------------------------------------- /.github/workflows/license-check.yaml: -------------------------------------------------------------------------------- 1 | name: License check 2 | 3 | on: 4 | - pull_request 5 | 6 | jobs: 7 | Test: 8 | runs-on: ubuntu-22.04 9 | steps: 10 | - name: Check License Header 11 | uses: apache/skywalking-eyes@v0.4.0 12 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | UpdateReleaseDraft: 10 | runs-on: ubuntu-22.04 11 | steps: 12 | - uses: release-drafter/release-drafter@v5 13 | env: 14 | GITHUB_TOKEN: ${{ secrets.GH_PUBLISH_SECRETS }} 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | .idea/ 3 | coverage.out 4 | *-coverage.out 5 | dist/ 6 | .vscode/launch.json 7 | sample.yaml 8 | .DS_Store 9 | console/atest-ui/node_modules 10 | cmd/data/index.html 11 | cmd/data/index.js 12 | cmd/data/index.css 13 | helm/*.tgz 14 | helm/api-testing/*.tgz 15 | oryxBuildBinary 16 | /helm/api-testing/charts/ 17 | console/atest-desktop/out 18 | console/atest-desktop/node_modules 19 | console/atest-desktop/atest 20 | console/atest-desktop/atest.exe 21 | console/atest-desktop/coverage 22 | atest-store-git 23 | .db 24 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | 2 | tasks: 3 | - init: make init-env install-precheck 4 | before: IMG_TOOL=docker GOPROXY= make build-image 5 | command: cd console/atest-ui/ && npm i 6 | 7 | ports: 8 | - port: 5713 # console interactive port 9 | 10 | vscode: 11 | extensions: 12 | - linuxsuren.api-testing 13 | - golang.go 14 | - Vue.volar 15 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | # This is an example .goreleaser.yml file with some sensible defaults. 2 | # Make sure to check the documentation at https://goreleaser.com 3 | before: 4 | hooks: 5 | # You may remove this if you don't use go modules. 6 | - go mod tidy 7 | - make embed-ui 8 | builds: 9 | - env: 10 | - CGO_ENABLED=0 11 | id: atest 12 | binary: atest 13 | goos: 14 | - linux 15 | - windows 16 | - darwin 17 | goarch: 18 | - amd64 19 | - arm64 20 | ldflags: 21 | - -w 22 | - -s 23 | - -X github.com/linuxsuren/api-testing/pkg/version.version={{.Version}} 24 | archives: 25 | - name_template: "{{ .Binary }}-{{ .Os }}-{{ .Arch }}" 26 | builds: 27 | - atest 28 | format_overrides: 29 | - goos: windows 30 | format: zip 31 | files: 32 | - README.md 33 | checksum: 34 | name_template: 'checksums.txt' 35 | snapshot: 36 | name_template: "{{ incpatch .Version }}-next" 37 | changelog: 38 | sort: asc 39 | filters: 40 | exclude: 41 | - '^docs:' 42 | - '^test:' 43 | -------------------------------------------------------------------------------- /.licenserc.yaml: -------------------------------------------------------------------------------- 1 | header: 2 | license: 3 | spdx-id: Apache License 4 | copyright-owner: API Testing Authors 5 | 6 | paths-ignore: 7 | - 'dist' 8 | - 'licenses' 9 | - '**/*.md' 10 | - 'LICENSE' 11 | - 'NOTICE' 12 | 13 | comment: on-failure 14 | -------------------------------------------------------------------------------- /.remarkrc: -------------------------------------------------------------------------------- 1 | listItemIndent=one 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "linuxsuren.api-testing", 4 | "redhat.vscode-yaml" 5 | ] 6 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # All make targets should be implemented in tools/make/*.mk 2 | # ==================================================================================================== 3 | # Supported Targets: (Run `make help` to see more API Testing information) 4 | # ==================================================================================================== 5 | 6 | # An wrapper around `make` so that we can force on the, 7 | # --warn-undefined-variables flag. Sure, you can set 8 | # `MAKEFLAGS += --warn-undefined-variables` from inside of a Makefile, 9 | # but then it won't turn on until the second phase (recipe execution), 10 | # and won't actually be on during the initial phase (parsing). 11 | # See: https://www.gnu.org/software/make/manual/make.html#Reading-Makefiles 12 | 13 | # Have everything-else ("%") depend on _run (which uses 14 | # $(MAKECMDGOALS) to decide what to run), rather than having 15 | # everything else run $(MAKE) directly, since that'd end up running 16 | # multiple sub-Makes if you give multiple targets on the CLI. 17 | 18 | _run: 19 | @$(MAKE) --warn-undefined-variables -f tools/make/common.mk $(MAKECMDGOALS) 20 | 21 | .PHONY: _run 22 | $(if $(MAKECMDGOALS),$(MAKECMDGOALS): %: _run) 23 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ## Reporting Security Issues 2 | 3 | The API Testing commnity takes a rigorous standpoint in annihilating the security issues in its software projects. API Testing is highly sensitive and forthcoming to issues pertaining to its features and functionality. 4 | 5 | ## REPORTING VULNERABILITY 6 | 7 | If you have apprehensions regarding API Testing's security or you discover vulnerability or potential threat, don’t hesitate to get in touch with the api-testing Security Team by dropping a mail at [api-testing-security@googlegroups.com](mailto:api-testing-security@googlegroups.com). In the mail, specify the description of the issue or potential threat. You are also urged to recommend the way to reproduce and replicate the issue. The API Testing community will get back to you after assessing and analysing the findings. 8 | 9 | PLEASE PAY ATTENTION to report the security issue on the security email before disclosing it on public domain. 10 | 11 | ## VULNERABILITY HANDLING 12 | 13 | An overview of the vulnerability handling process is: 14 | 15 | The reporter reports the vulnerability privately to API Testing community. 16 | The appropriate project's security team works privately with the reporter to resolve the vulnerability. 17 | A new release of the API Testing product concerned is made that includes the fix. 18 | The vulnerability is publically announced. 19 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'API testing with Kubernetes' 2 | description: 'API testing with Kubernetes' 3 | inputs: 4 | pattern: 5 | description: 'The pattern of the items' 6 | required: true 7 | default: 'testcase-*.yaml' 8 | kustomization: 9 | description: 'The kustomization file path' 10 | required: true 11 | waitNamespace: 12 | description: 'waitNamespace' 13 | required: true 14 | waitResource: 15 | description: 'waitResource' 16 | required: true 17 | runs: 18 | using: 'docker' 19 | image: 'Dockerfile' 20 | args: 21 | - ${{ inputs.pattern }} 22 | - ${{ inputs.kustomization }} 23 | - ${{ inputs.waitNamespace }} 24 | - ${{ inputs.waitResource }} 25 | -------------------------------------------------------------------------------- /checklink_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignorePatterns": [ 3 | { 4 | "pattern": "^(https?://)?(127.0.0.1|localhost|192.168.33.1|somehost\\.com)" 5 | } 6 | ], 7 | "aliveStatusCodes": [ 8 | 200 9 | ] 10 | } -------------------------------------------------------------------------------- /cmd/data/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/cmd/data/favicon.ico -------------------------------------------------------------------------------- /cmd/data/font/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/cmd/data/font/.keep -------------------------------------------------------------------------------- /cmd/data/image/warn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/cmd/data/image/warn.jpg -------------------------------------------------------------------------------- /cmd/data/index.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/cmd/data/index.css -------------------------------------------------------------------------------- /cmd/data/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/cmd/data/index.html -------------------------------------------------------------------------------- /cmd/data/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/cmd/data/index.js -------------------------------------------------------------------------------- /cmd/jsonschema.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cmd 18 | 19 | import ( 20 | "encoding/json" 21 | 22 | "github.com/invopop/jsonschema" 23 | "github.com/linuxsuren/api-testing/pkg/testing" 24 | "github.com/spf13/cobra" 25 | ) 26 | 27 | func createJSONSchemaCmd() (c *cobra.Command) { 28 | c = &cobra.Command{ 29 | Use: "json", 30 | Short: "Print the JSON schema of the test suites struct", 31 | RunE: func(cmd *cobra.Command, args []string) (err error) { 32 | var data []byte 33 | schema := jsonschema.Reflect(&testing.TestSuite{}) 34 | if data, err = json.MarshalIndent(schema, "", " "); err == nil { 35 | cmd.Println(string(data)) 36 | } 37 | return 38 | }, 39 | } 40 | return 41 | } 42 | -------------------------------------------------------------------------------- /cmd/jsonschema_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cmd_test 18 | 19 | import ( 20 | "bytes" 21 | "strings" 22 | "testing" 23 | 24 | "github.com/linuxsuren/api-testing/cmd" 25 | "github.com/linuxsuren/api-testing/pkg/server" 26 | fakeruntime "github.com/linuxsuren/go-fake-runtime" 27 | "github.com/stretchr/testify/assert" 28 | ) 29 | 30 | func TestJSONSchemaCmd(t *testing.T) { 31 | c := cmd.NewRootCmd(&fakeruntime.FakeExecer{ExpectOS: "linux"}, 32 | server.NewFakeHTTPServer()) 33 | 34 | buf := new(bytes.Buffer) 35 | c.SetOut(buf) 36 | 37 | c.SetArgs([]string{"json"}) 38 | err := c.Execute() 39 | assert.Nil(t, err) 40 | assert.True(t, strings.Contains(buf.String(), "schema")) 41 | } 42 | -------------------------------------------------------------------------------- /cmd/sample.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cmd 18 | 19 | import ( 20 | "github.com/linuxsuren/api-testing/sample" 21 | "github.com/spf13/cobra" 22 | ) 23 | 24 | func createSampleCmd() (c *cobra.Command) { 25 | c = &cobra.Command{ 26 | Use: "sample", 27 | Short: "Generate a sample test case YAML file", 28 | RunE: func(cmd *cobra.Command, args []string) (err error) { 29 | cmd.Println(sample.TestSuiteGitLab) 30 | return 31 | }, 32 | } 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /cmd/sample_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cmd_test 18 | 19 | import ( 20 | "bytes" 21 | "testing" 22 | 23 | "github.com/linuxsuren/api-testing/cmd" 24 | "github.com/linuxsuren/api-testing/pkg/server" 25 | "github.com/linuxsuren/api-testing/sample" 26 | fakeruntime "github.com/linuxsuren/go-fake-runtime" 27 | "github.com/stretchr/testify/assert" 28 | ) 29 | 30 | func TestSampleCmd(t *testing.T) { 31 | c := cmd.NewRootCmd(&fakeruntime.FakeExecer{ExpectOS: "linux"}, 32 | server.NewFakeHTTPServer()) 33 | 34 | buf := new(bytes.Buffer) 35 | c.SetOut(buf) 36 | 37 | c.SetArgs([]string{"sample"}) 38 | err := c.Execute() 39 | assert.Nil(t, err) 40 | assert.Equal(t, sample.TestSuiteGitLab+"\n", buf.String()) 41 | } 42 | -------------------------------------------------------------------------------- /cmd/testdata/invalid-api.yaml: -------------------------------------------------------------------------------- 1 | name: Simple 2 | api: "{{.api}" 3 | items: 4 | - request: 5 | api: /bar 6 | name: bar 7 | -------------------------------------------------------------------------------- /cmd/testdata/invalid-schema.yaml: -------------------------------------------------------------------------------- 1 | name: Simple 2 | api: "{{.api}" 3 | item: 4 | - requests: 5 | api: /bar 6 | method: POSt 7 | -------------------------------------------------------------------------------- /cmd/testdata/postman.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "0da1f6bf-fdbb-46a5-ac46-873564e2259c", 4 | "name": "New Collection", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 6 | "_exporter_id": "6795120", 7 | "_collection_link": "https://www.postman.com/ks-devops/workspace/kubesphere-devops/collection/6795120-0da1f6bf-fdbb-46a5-ac46-873564e2259c?action=share&creator=6795120&source=collection_link" 8 | }, 9 | "item": [ 10 | { 11 | "name": "New Request", 12 | "protocolProfileBehavior": { 13 | "disableBodyPruning": true 14 | }, 15 | "request": { 16 | "method": "GET", 17 | "header": [ 18 | { 19 | "key": "key", 20 | "value": "value", 21 | "description": "description", 22 | "type": "text" 23 | } 24 | ], 25 | "body": { 26 | "mode": "raw", 27 | "raw": "{}" 28 | }, 29 | "url": { 30 | "raw": "http://localhost?key=value" 31 | } 32 | } 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /cmd/testdata/simple-suite.yaml: -------------------------------------------------------------------------------- 1 | name: Simple 2 | api: http://foo 3 | items: 4 | - request: 5 | api: /bar 6 | name: bar 7 | -------------------------------------------------------------------------------- /cmd/testdata/stores.yaml: -------------------------------------------------------------------------------- 1 | stores: 2 | - name: git 3 | kind: 4 | name: atest-store-git 5 | enabled: true 6 | url: xxx 7 | readonly: false 8 | disabled: false 9 | plugins: 10 | - name: atest-store-git 11 | url: unix:///tmp/atest-store-git.sock 12 | enabled: true 13 | -------------------------------------------------------------------------------- /console/atest-desktop/README.md: -------------------------------------------------------------------------------- 1 | ```shell 2 | npx electron-forge import 3 | ``` 4 | 5 | ```shell 6 | npm config set registry https://registry.npmmirror.com 7 | ``` 8 | 9 | ## Package 10 | 11 | ```shell 12 | npm run package -- --platform=darwin 13 | npm run package -- --platform=win32 14 | npm run package -- --platform=linux 15 | ``` 16 | 17 | ## For Linux 18 | 19 | You need to install tools if you want to package Windows on Linux: 20 | ```shell 21 | apt install wine64 zip -y 22 | ``` 23 | 24 | ## For Windows 25 | 26 | ```powershell 27 | dotnet tool install --global wix 28 | ``` 29 | 30 | ## Publish 31 | 32 | export GITHUB_TOKEN=your-token 33 | 34 | ```shell 35 | npm run publish -- --platform=darwin 36 | npm run publish -- --platform=linux 37 | ``` 38 | -------------------------------------------------------------------------------- /console/atest-desktop/api-testing.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/console/atest-desktop/api-testing.icns -------------------------------------------------------------------------------- /console/atest-desktop/api-testing.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/console/atest-desktop/api-testing.ico -------------------------------------------------------------------------------- /console/atest-desktop/api-testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/console/atest-desktop/api-testing.png -------------------------------------------------------------------------------- /console/atest-desktop/api.test.js: -------------------------------------------------------------------------------- 1 | const { getPort, getHealthzUrl, getHomePage } = require('./api'); 2 | 3 | describe('getPort function', () => { 4 | test('should return the default port number 7788', () => { 5 | const port = getPort(); 6 | expect(port).toBe(7788); 7 | }); 8 | }); 9 | 10 | describe('getHealthzUrl function', () => { 11 | test('should return the default healthz url', () => { 12 | const url = getHealthzUrl(); 13 | expect(url).toBe('http://localhost:7788/healthz'); 14 | }); 15 | }); 16 | 17 | describe('getHomePage function', () => { 18 | test('should return the default home page url', () => { 19 | const url = getHomePage(); 20 | expect(url).toBe('http://localhost:7788'); 21 | }); 22 | }) 23 | -------------------------------------------------------------------------------- /console/atest-ui/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | require('@rushstack/eslint-patch/modern-module-resolution') 3 | 4 | module.exports = { 5 | root: true, 6 | 'extends': [ 7 | 'plugin:vue/vue3-essential', 8 | 'eslint:recommended', 9 | '@vue/eslint-config-typescript', 10 | '@vue/eslint-config-prettier/skip-formatting' 11 | ], 12 | overrides: [ 13 | { 14 | files: [ 15 | 'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}' 16 | ], 17 | 'extends': [ 18 | 'plugin:cypress/recommended' 19 | ] 20 | } 21 | ], 22 | parserOptions: { 23 | ecmaVersion: 'latest' 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /console/atest-ui/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /console/atest-ui/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc", 3 | "semi": false, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "printWidth": 100, 7 | "trailingComma": "none" 8 | } -------------------------------------------------------------------------------- /console/atest-ui/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /console/atest-ui/cypress.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'cypress' 2 | 3 | export default defineConfig({ 4 | e2e: { 5 | specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', 6 | baseUrl: 'http://localhost:4173' 7 | } 8 | }) 9 | -------------------------------------------------------------------------------- /console/atest-ui/cypress/e2e/gRPC.cy.ts: -------------------------------------------------------------------------------- 1 | import { createTestCase, createTestSuite, selectTestCase, selectTestCaseTab, userID_Alpha } from './util' 2 | 3 | describe('gRPC', () => { 4 | const suiteName = userID_Alpha() 5 | const store = "local" 6 | const sampleAPIAddress = "http://foo" 7 | 8 | it('Create Suite', () => { 9 | cy.visit('/') 10 | cy.get('.introjs-skipbutton').click() 11 | cy.get('[test-id="testing-menu"]').click() 12 | 13 | createTestSuite(store, 'gRPC', suiteName, sampleAPIAddress) 14 | }) 15 | 16 | const caseName = userID_Alpha() 17 | const caseAPI = "/api/v2" 18 | it('New Test Case', () => { 19 | cy.visit('/') 20 | cy.get('.introjs-skipbutton').click() 21 | createTestCase(suiteName, caseName, caseAPI) 22 | }) 23 | 24 | it('Update Test Case', () => { 25 | cy.visit('/') 26 | cy.get('.introjs-skipbutton').click() 27 | selectTestCase(caseName) 28 | selectTestCaseTab('tab-second') 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /console/atest-ui/cypress/e2e/http.cy.ts: -------------------------------------------------------------------------------- 1 | // https://on.cypress.io/api 2 | // https://docs.cypress.io/api/table-of-contents 3 | import { createTestCase, createTestSuite, selectTestCase, selectTestSuite, userID_Alpha } from './util' 4 | 5 | describe('Suite Manage', () => { 6 | const suiteName = userID_Alpha() 7 | const store = "local" 8 | const sampleAPIAddress = "http://foo" 9 | 10 | it('Create Suite', () => { 11 | cy.visit('/') 12 | cy.get('.introjs-skipbutton').click() 13 | cy.get('[test-id="testing-menu"]').click() 14 | 15 | cy.contains('span', 'Tool Box') 16 | createTestSuite(store, 'HTTP', suiteName, sampleAPIAddress) 17 | }) 18 | 19 | const caseName = userID_Alpha() 20 | const caseMethod = "GET" 21 | const caseAPI = "/api/v2" 22 | it('New Test Case', () => { 23 | cy.visit('/') 24 | cy.get('.introjs-skipbutton').click() 25 | createTestCase(suiteName, caseName, caseAPI) 26 | }) 27 | 28 | it('Find Test Case', () => { 29 | cy.visit('/') 30 | cy.get('.introjs-skipbutton').click() 31 | selectTestCase(caseName) 32 | 33 | // verify the value 34 | cy.get('[test-id="case-editor-method"] input').should('have.value', caseMethod) 35 | }) 36 | 37 | it('Delete Suite', () => { 38 | cy.visit('/') 39 | cy.get('.introjs-skipbutton').click() 40 | selectTestSuite(suiteName) 41 | 42 | cy.get('[test-id="suite-editor-api"]').should('have.value', sampleAPIAddress) 43 | cy.get('[test-id="suite-del-but"]').click() 44 | }) 45 | }) 46 | -------------------------------------------------------------------------------- /console/atest-ui/cypress/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["./**/*", "../support/**/*"], 4 | "compilerOptions": { 5 | "isolatedModules": false, 6 | "target": "es5", 7 | "lib": ["es5", "dom"], 8 | "types": ["cypress"] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /console/atest-ui/cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } 6 | -------------------------------------------------------------------------------- /console/atest-ui/cypress/support/e2e.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands' 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /console/atest-ui/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /console/atest-ui/gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./node_modules/.bin/grpc_tools_node_protoc --plugin=protoc-gen-ts=. --ts_out=../../pkg/server -I ../../pkg/server ../../pkg/server/server.proto -------------------------------------------------------------------------------- /console/atest-ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | API Testing 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /console/atest-ui/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/console/atest-ui/public/favicon.ico -------------------------------------------------------------------------------- /console/atest-ui/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /console/atest-ui/src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import './base.css'; 2 | 3 | #app { 4 | margin: 0 auto; 5 | padding: 1rem; 6 | padding-top: 40px; 7 | height: 100vh; 8 | font-weight: normal; 9 | } 10 | 11 | .top-menu { 12 | position: absolute; 13 | top: 10px; 14 | right: 20px; 15 | } 16 | 17 | a, 18 | .green { 19 | text-decoration: none; 20 | color: hsla(160, 100%, 37%, 1); 21 | transition: 0.4s; 22 | } 23 | 24 | @media (hover: hover) { 25 | a:hover { 26 | background-color: hsla(160, 100%, 37%, 0.2); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /console/atest-ui/src/components/Button.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /console/atest-ui/src/components/EditButton.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 48 | -------------------------------------------------------------------------------- /console/atest-ui/src/theme.ts: -------------------------------------------------------------------------------- 1 | const lightTheme: { [k: string]: string } = { 2 | '--color-background': 'var(--vt-c-white)', 3 | '--color-background-soft': 'var(--vt-c-white-soft)', 4 | '--color-background-mute': 'var(--vt-c-white-mute)', 5 | '--color-border': 'var(--vt-c-divider-light-2)', 6 | '--color-border-hover': 'var(--vt-c-divider-light-1)', 7 | '--color-heading': 'var(--vt-c-text-light-1)', 8 | '--color-text': 'var(--vt-c-text-light-1)' 9 | } 10 | 11 | const darkTheme: { [k: string]: string } = { 12 | '--color-background': 'var(--vt-c-black)', 13 | '--color-background-soft': 'var(--vt-c-black-soft)', 14 | '--color-background-mute': 'var(--vt-c-black-mute)', 15 | '--color-border': 'var(--vt-c-divider-dark-2)', 16 | '--color-border-hover': 'var(--vt-c-divider-dark-1)', 17 | '--color-heading': 'var(--vt-c-text-dark-1)', 18 | '--color-text': 'var(--vt-c-text-dark-2)' 19 | } 20 | 21 | 22 | export default function setAsDarkTheme(darkMode: boolean) { 23 | const theme = darkMode ? darkTheme : lightTheme 24 | Object.keys(theme).forEach((key) => { 25 | document.documentElement.style.setProperty(key, theme[key]) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /console/atest-ui/src/views/APIInput.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 36 | -------------------------------------------------------------------------------- /console/atest-ui/src/views/__test__/store.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | import { SupportedExtension, SupportedExtensions } from "../store"; 18 | 19 | describe("SupportedExtensions", () => { 20 | test('length check', () => { 21 | const extensions = SupportedExtensions() 22 | expect(extensions.length).toBe(10) 23 | }) 24 | 25 | for (const extension of SupportedExtensions()) { 26 | test(`${extension.name} check`, () => { 27 | expect(SupportedExtension(extension.name)).not.toBeUndefined() 28 | }) 29 | } 30 | }) 31 | -------------------------------------------------------------------------------- /console/atest-ui/src/views/magicKeys.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | import { watch } from 'vue' 18 | import { useMagicKeys } from '@vueuse/core' 19 | 20 | function Keys(func: (() => void) | ((k: string) => void), keys: string[]) { 21 | const magicKeys = useMagicKeys() 22 | keys.forEach(k => { 23 | watch(magicKeys[k], (v) => { 24 | if (v) func(k) 25 | }) 26 | }) 27 | } 28 | 29 | export const Magic = { 30 | Keys 31 | } 32 | -------------------------------------------------------------------------------- /console/atest-ui/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "vue.config.ts"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "baseUrl": ".", 8 | "paths": { 9 | "@/*": ["./src/*"] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /console/atest-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "compilerOptions":{ 4 | "module":"commonjs", 5 | "allowJs": true, 6 | "target": "es6", 7 | "esModuleInterop": true 8 | }, 9 | "references": [ 10 | { 11 | "path": "./tsconfig.node.json" 12 | }, 13 | { 14 | "path": "./tsconfig.app.json" 15 | }, 16 | { 17 | "path": "./tsconfig.vitest.json" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /console/atest-ui/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node18/tsconfig.json", 3 | "include": [ 4 | "vite.config.*", 5 | "vitest.config.*", 6 | "cypress.config.*", 7 | "nightwatch.conf.*", 8 | "playwright.config.*" 9 | ], 10 | "compilerOptions": { 11 | "composite": true, 12 | "module": "ESNext", 13 | "types": ["node"] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /console/atest-ui/tsconfig.vitest.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.app.json", 3 | "exclude": [], 4 | "compilerOptions": { 5 | "composite": true, 6 | "lib": [], 7 | "types": ["node", "jsdom"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /console/atest-ui/ui.go: -------------------------------------------------------------------------------- 1 | package ui 2 | 3 | import ( 4 | _ "embed" 5 | "encoding/json" 6 | ) 7 | 8 | //go:embed package.json 9 | var packageJSON []byte 10 | 11 | type JSON struct { 12 | Dependencies map[string]string `json:"dependencies"` 13 | DevDependencies map[string]string `json:"devDependencies"` 14 | } 15 | 16 | func GetPackageJSON() (data JSON) { 17 | data = JSON{} 18 | _ = json.Unmarshal(packageJSON, &data) 19 | return 20 | } 21 | -------------------------------------------------------------------------------- /console/atest-ui/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url' 2 | import { mergeConfig } from 'vite' 3 | import { configDefaults, defineConfig } from 'vitest/config' 4 | import viteConfig from './vite.config' 5 | 6 | export default mergeConfig( 7 | viteConfig, 8 | defineConfig({ 9 | test: { 10 | globals:true, 11 | // environment: 'jsdom', 12 | environment: 'happy-dom', 13 | exclude: [...configDefaults.exclude, 'e2e/*'], 14 | root: fileURLToPath(new URL('./', import.meta.url)), 15 | transformMode: { 16 | web: [/\.[jt]sx$/] 17 | } 18 | } 19 | }) 20 | ) 21 | -------------------------------------------------------------------------------- /docs/constants.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package docs 17 | 18 | import ( 19 | _ "embed" 20 | "fmt" 21 | yamlconv "github.com/ghodss/yaml" 22 | "github.com/xeipuuv/gojsonschema" 23 | ) 24 | 25 | //go:embed api-testing-schema.json 26 | var Schema string 27 | 28 | //go:embed api-testing-mock-schema.json 29 | var MockSchema string 30 | 31 | func Validate(data []byte, schema string) (err error) { 32 | // convert YAML to JSON 33 | var jsonData []byte 34 | if jsonData, err = yamlconv.YAMLToJSON(data); err == nil { 35 | schemaLoader := gojsonschema.NewStringLoader(schema) 36 | documentLoader := gojsonschema.NewBytesLoader(jsonData) 37 | 38 | var result *gojsonschema.Result 39 | if result, err = gojsonschema.Validate(schemaLoader, documentLoader); err == nil { 40 | if !result.Valid() { 41 | err = fmt.Errorf("%v", result.Errors()) 42 | } 43 | } 44 | } 45 | return 46 | } 47 | -------------------------------------------------------------------------------- /docs/manifests/argocd/simple.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: argoproj.io/v1alpha1 2 | kind: Application 3 | metadata: 4 | name: api-testing 5 | namespace: argocd 6 | spec: 7 | destination: 8 | namespace: default 9 | server: https://kubernetes.default.svc 10 | project: default 11 | source: 12 | path: sample/kubernetes/default 13 | repoURL: https://github.com/LinuxSuRen/api-testing 14 | targetRevision: master 15 | # see also https://argo-cd.readthedocs.io/en/stable/user-guide/kustomize/ 16 | kustomize: 17 | images: 18 | - ghcr.io/linuxsuren/api-testing=ghcr.io/linuxsuren/api-testing:master 19 | syncPolicy: 20 | syncOptions: 21 | - CreateNamespace=true 22 | - RespectIgnoreDifferences=true 23 | automated: 24 | prune: true 25 | selfHeal: true 26 | -------------------------------------------------------------------------------- /docs/manifests/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | services: 3 | testing: 4 | image: "linuxsuren.docker.scarf.sh/linuxsuren/api-testing:master" 5 | ports: 6 | - 8080:8080 7 | etcd: 8 | image: "bitnami/etcd:3.5.10" 9 | expose: 10 | - "2379" 11 | environment: 12 | ALLOW_NONE_AUTHENTICATION: "yes" 13 | -------------------------------------------------------------------------------- /docs/manifests/kubernetes/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifest.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | images: 6 | - name: ghcr.io/linuxsuren/api-testing:master 7 | newName: ghcr.io/linuxsuren/api-testing 8 | newTag: master 9 | -------------------------------------------------------------------------------- /docs/manifests/kubernetes/docker.io/kustomization.yaml: -------------------------------------------------------------------------------- 1 | bases: 2 | - ../default 3 | 4 | apiVersion: kustomize.config.k8s.io/v1beta1 5 | kind: Kustomization 6 | images: 7 | - name: ghcr.io/linuxsuren/api-testing:master 8 | newName: linuxsuren/api-testing 9 | newTag: master 10 | -------------------------------------------------------------------------------- /docs/manifests/podman.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | labels: 5 | app: api-testing 6 | name: api-testing 7 | spec: 8 | containers: 9 | - image: ghcr.io/linuxsuren/api-testing:master 10 | name: web 11 | ports: 12 | - containerPort: 8080 13 | hostPort: 8080 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /root/.config/atest/ 17 | name: config 18 | tty: true 19 | workingDir: / 20 | - image: ghcr.io/linuxsuren/api-testing:master 21 | name: extension-orm 22 | command: [atest-store-orm] 23 | tty: true 24 | workingDir: / 25 | - image: ghcr.io/linuxsuren/api-testing:master 26 | name: extension-s3 27 | command: [atest-store-s3] 28 | tty: true 29 | workingDir: / 30 | - image: ghcr.io/linuxsuren/api-testing:master 31 | name: extension-git 32 | command: [atest-store-git] 33 | tty: true 34 | workingDir: / 35 | volumes: 36 | - name: config 37 | hostPath: 38 | path: /root/.config/atest/ 39 | type: DirectoryOrCreate 40 | -------------------------------------------------------------------------------- /docs/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": {} 6 | } 7 | -------------------------------------------------------------------------------- /docs/site/.dockerignore: -------------------------------------------------------------------------------- 1 | console/atest-ui/node_modules 2 | console/atest-ui/dist 3 | .git/ 4 | bin/ 5 | dist/ 6 | .vscode/ 7 | -------------------------------------------------------------------------------- /docs/site/.gitignore: -------------------------------------------------------------------------------- 1 | /public 2 | resources/ 3 | node_modules/ 4 | package-lock.json 5 | .hugo_build.lock -------------------------------------------------------------------------------- /docs/site/.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* 2 | -------------------------------------------------------------------------------- /docs/site/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM klakegg/hugo:ext-alpine@sha256:536dd4805d0493ee13bf1f3df3852ed1f26d1625983507c8c56242fc029b44c7 2 | 3 | RUN apk add git && \ 4 | git config --global --add safe.directory /src 5 | -------------------------------------------------------------------------------- /docs/site/assets/atest-vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/docs/site/assets/atest-vscode.png -------------------------------------------------------------------------------- /docs/site/assets/icons/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/docs/site/assets/icons/logo.png -------------------------------------------------------------------------------- /docs/site/assets/scss/_variables_project.scss: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Add styles or override variables from the theme here. 4 | 5 | */ 6 | 7 | $primary: #1e71ec; 8 | $secondary: #ffffff; 9 | $dark: #4a9ff5; 10 | -------------------------------------------------------------------------------- /docs/site/config.yaml: -------------------------------------------------------------------------------- 1 | # THIS IS A TEST CONFIG ONLY! 2 | # FOR THE CONFIGURATION OF YOUR SITE USE hugo.yaml. 3 | # 4 | # As of Docsy 0.7.0, Hugo 0.110.0 or later must be used. 5 | # 6 | # The sole purpose of this config file is to detect Hugo-module builds that use 7 | # an older version of Hugo. 8 | # 9 | # DO NOT add any config parameters to this file. You can safely delete this file 10 | # if your project is using the required Hugo version. 11 | 12 | module: 13 | hugoVersion: 14 | extended: true 15 | min: 0.110.0 16 | -------------------------------------------------------------------------------- /docs/site/content/en/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: API Testing 3 | --- 4 | 5 | {{< blocks/cover title="Welcome to API Testing!" image_anchor="top" height="full" >}} 6 | }}"> 7 | GET STARTED 8 | 9 | }}"> 10 | CONTRIBUTING 11 | 12 |

YAML based API testing tool. interface debug and test tools.

13 | {{< blocks/link-down color="white" >}} 14 |

Let's improve the code quality together.

15 | {{< /blocks/cover >}} 16 | -------------------------------------------------------------------------------- /docs/site/content/en/about/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: About API Testing 3 | linkTitle: About 4 | --- 5 | 6 | {{% blocks/cover title="About API Testing" height="auto" %}} 7 | 8 | API Testing is an open source project for interface debug and test tools. 9 | 10 | Read on to find out more, or visit our [documentation](/latest/) to get started! 11 | {{% /blocks/cover %}} 12 | 13 | {{% blocks/section color="black" %}} 14 | 15 | ## Objectives 16 | 17 | --- 18 | 19 | // TBD. 20 | 21 | {{% /blocks/section %}} 22 | -------------------------------------------------------------------------------- /docs/site/content/en/contributions/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Get Involved" 3 | description = "This section includes contents related to Contributions" 4 | linktitle = "Get Involved" 5 | 6 | [[cascade]] 7 | type = "docs" 8 | +++ -------------------------------------------------------------------------------- /docs/site/content/en/contributions/design/Todo.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Todo Add Design" 3 | weight: -100 4 | description: Todo. 5 | --- 6 | 7 | // TBD 8 | -------------------------------------------------------------------------------- /docs/site/content/en/contributions/design/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Design" 3 | weight: -100 4 | description: This section includes Designs of API Testing. 5 | --- 6 | -------------------------------------------------------------------------------- /docs/site/content/en/contributions/roadmap.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Roadmap" 3 | weight: -1 4 | description: "This section records the roadmap of API Testing." 5 | --- 6 | 7 | // TBD 8 | -------------------------------------------------------------------------------- /docs/site/content/en/latest/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Welcome to API Testing" 3 | linktitle = "Documentation" 4 | description = "API Testing Documents" 5 | 6 | [[cascade]] 7 | type = "docs" 8 | +++ 9 | 10 | {{% alert title="Note" color="primary" %}} 11 | 12 | This project is under **active** development. Many features are not complete. We would love for you to [Get Involved](/contributions)! 13 | 14 | {{% /alert %}} 15 | 16 | // TBD. 17 | 18 | ## Ready to get started? 19 | -------------------------------------------------------------------------------- /docs/site/content/en/latest/api/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "API" 3 | description: This section includes APIs of API Testing. 4 | weight: 80 5 | --- 6 | -------------------------------------------------------------------------------- /docs/site/content/en/latest/api/extension_types.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "API Reference" 3 | +++ 4 | 5 | // TBD. 6 | -------------------------------------------------------------------------------- /docs/site/content/en/latest/install/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Installation" 3 | description: This section includes installation related contents of API Testing. 4 | weight: 70 5 | --- 6 | -------------------------------------------------------------------------------- /docs/site/content/en/latest/install/install-locally.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Install with Locally" 3 | weight = -99 4 | +++ 5 | 6 | // TBD 7 | 8 | Install API Testing. 9 | -------------------------------------------------------------------------------- /docs/site/content/en/latest/releases/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Releases" 3 | weight: 90 4 | description: This section includes Releases of API Testing. 5 | --- 6 | -------------------------------------------------------------------------------- /docs/site/content/en/latest/releases/v0.1.0.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "v0.1.0" 3 | publishdate: 2022-05-16 4 | --- 5 | 6 | Date: 2024 06 01 7 | 8 | // TBD 9 | -------------------------------------------------------------------------------- /docs/site/content/en/latest/tasks/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Tasks" 3 | weight: 2 4 | description: Learn API Testing hands-on through tasks 5 | --- 6 | -------------------------------------------------------------------------------- /docs/site/content/en/latest/tasks/mock-server.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Mock server get started" 3 | weight = -99 4 | +++ 5 | 6 | ## Get started 7 | 8 | You can start a mock server of [container registry](https://distribution.github.io/distribution/) with below command: 9 | 10 | ```shell 11 | atest mock --prefix / mock/image-registry.yaml 12 | ``` 13 | 14 | then, you can pull images from it: 15 | 16 | ```shell 17 | docker pull localhost:6060/repo/name:tag 18 | ``` 19 | -------------------------------------------------------------------------------- /docs/site/content/en/latest/tasks/prometheus.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Pushing the test results into Prometheus" 3 | +++ 4 | 5 | You can use the following command to do it: 6 | 7 | ```shell 8 | atest run --report prometheus --report-file http://localhost:9091 \ 9 | -p sample/testsuite-gitee.yaml --duration 30m --qps 1 10 | ``` 11 | 12 | It will push the test results data into Prometheus [PushGateway](https://github.com/prometheus/pushgateway). 13 | Then Prometheus could get the metrics from it. 14 | 15 | Skip the following instructions if you are familiar with Prometheus: 16 | 17 | ```shell 18 | docker run \ 19 | -p 9090:9090 \ 20 | -v /etc/timezone:/etc/timezone:ro \ 21 | -v /etc/localtime:/etc/localtime:ro \ 22 | -v /root/prometheus.yml:/etc/prometheus/prometheus.yml \ 23 | prom/prometheus 24 | 25 | docker run -p 9091:9091 \ 26 | -v /etc/timezone:/etc/timezone:ro \ 27 | -v /etc/localtime:/etc/localtime:ro \ 28 | prom/pushgateway 29 | 30 | docker run -p 3000:3000 docker.io/grafana/grafana 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/site/content/en/latest/tasks/quickstart.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Quickstart" 3 | weight: 1 4 | description: Get started with API Testing in a few simple steps. 5 | --- 6 | 7 | // TBD 8 | -------------------------------------------------------------------------------- /docs/site/content/en/news/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "News" 3 | linktitle = "News" 4 | description = "API Testing News" 5 | 6 | [[cascade]] 7 | type = "docs" 8 | +++ 9 | 10 | This is the **News** section. It is organized into three categories: blogs, presentations and releases. 11 | 12 | The files in these directories will be listed in reverse chronological order. 13 | -------------------------------------------------------------------------------- /docs/site/content/en/news/blogs/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Blogs" 3 | description = "API Testing Blogs" 4 | linktitle = "Blogs" 5 | 6 | [[cascade]] 7 | type = "docs" 8 | +++ 9 | -------------------------------------------------------------------------------- /docs/site/content/en/news/presentations/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Presentations" 3 | description = "API Testing Presentations and activities." 4 | linktitle = "Presentations" 5 | 6 | [[cascade]] 7 | type = "docs" 8 | +++ 9 | -------------------------------------------------------------------------------- /docs/site/content/en/news/releases/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Posting Notice" 3 | description = "API Testing posting notice" 4 | linktitle = "Posting" 5 | 6 | [[cascade]] 7 | type = "docs" 8 | +++ 9 | 10 | This document provides details on API Testing releases. 11 | API Testing follows the Semantic Version Control [v2.0.0 specification](https://semver.org/) for release version control. 12 | Since API Testing is a new project, minor versions are the only versions defined. 13 | Additional release details, such as patch versions, will be created by API Testing maintainers at a future date. 14 | 15 | ## Stable releases {#stable-releases} 16 | 17 | 18 | 19 | ## Release management {#release-management}} 20 | 21 | 22 | 23 | ## Release schedule} {#release-schedule} 24 | -------------------------------------------------------------------------------- /docs/site/content/en/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Search Results 3 | layout: search 4 | --- 5 | -------------------------------------------------------------------------------- /docs/site/content/zh/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: API Testing 3 | --- 4 | 5 | {{< blocks/cover title="欢迎访问 API Testing!" image_anchor="top" height="full" >}} 6 | }}"> 7 | 开始使用 8 | 9 | }}"> 10 | 参与贡献 11 | 12 |

开源接口调试 & 测试工具

13 | 14 | {{< blocks/link-down color="white" >}} 15 |

让我们一起提高代码质量吧!

16 | {{< /blocks/cover >}} 17 | -------------------------------------------------------------------------------- /docs/site/content/zh/about/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 关于 API Testing. 3 | linkTitle: 关于 4 | --- 5 | 6 | {{% blocks/cover title="About API Testing" height="auto" %}} 7 | 8 | API Testing (atest)是一个接口调试和测试工具的开源项目。 9 | 10 | 请继续阅读以了解更多信息,或访问我们的 [文档](/latest/) 开始使用! 11 | 12 | {{% /blocks/cover %}} 13 | 14 | {{% blocks/section color="black" %}} 15 | 16 | ## Objectives 17 | 18 | --- 19 | 20 | // TBD. 21 | 22 | {{% /blocks/section %}} 23 | -------------------------------------------------------------------------------- /docs/site/content/zh/contributions/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "参与其中" 3 | description = "本节包含与贡献相关的内容" 4 | linktitle = "参与其中" 5 | 6 | [[cascade]] 7 | type = "docs" 8 | +++ -------------------------------------------------------------------------------- /docs/site/content/zh/contributions/design/Goals.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "目标" 3 | weight: -1 4 | description: "API Testing goals." 5 | --- 6 | 7 | // TBD 8 | -------------------------------------------------------------------------------- /docs/site/content/zh/contributions/design/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "设计" 3 | weight: -100 4 | description: 这部分包含 API Testing 的设计细节. 5 | --- 6 | -------------------------------------------------------------------------------- /docs/site/content/zh/contributions/design/security-policy.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "安全策略" 3 | weight: -2 4 | description: "API Testing 安全策略。" 5 | --- 6 | 7 | // TBD 8 | -------------------------------------------------------------------------------- /docs/site/content/zh/contributions/roadmap.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "发展规划" 3 | weight: -1 4 | description: "API Testing roadmap." 5 | --- 6 | 7 | // TBD 8 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/api/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "API" 3 | description: 本节内容包含 API Testing 的 API。 4 | weight: 3 5 | --- 6 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/api/extension_types.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "API 引用" 3 | +++ 4 | 5 | // TBD. 6 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/install/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 安装 3 | description: 本节包含关于安装 API Testing 的内容。 4 | weight: 1 5 | --- 6 | 7 | atest 支持如下的安装使用场景: 8 | 9 | * 命令行 10 | * 持续集成流水线 11 | * 桌面应用 12 | * Web 页面 13 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/install/install-helm.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "Helm" 3 | description = "通过 Helm 安装的方式使用 API Testing" 4 | weight = -98 5 | +++ 6 | 7 | You could install `api-testing` via Helm chart: 8 | 9 | ```shell 10 | helm install atest oci://docker.io/linuxsuren/api-testing \ 11 | --version v0.0.2-helm \ 12 | --set service.type=NodePort 13 | ``` 14 | 15 | or upgrade it: 16 | 17 | ```shell 18 | helm upgrade atest oci://docker.io/surenpi/api-testing \ 19 | --version v0.0.2-helm \ 20 | --set image.tag=master \ 21 | --set replicaCount=3 22 | ``` 23 | 24 | ## SkyWalking 25 | 26 | ```shell 27 | helm install atest oci://docker.io/linuxsuren/api-testing \ 28 | --version v0.0.2-helm \ 29 | --set image.tag=master \ 30 | --set service.type=NodePort \ 31 | --set service.nodePort=30154 \ 32 | --set skywalking.endpoint.http=http://skywalking-skywalking-helm-oap.skywalking.svc:12800 \ 33 | --set skywalking.endpoint.grpc=skywalking-skywalking-helm-oap.skywalking.svc:11800 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/install/install-local.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "本地安装" 3 | weight = -99 4 | +++ 5 | 6 | ## 手动下载 7 | 8 | 您可以通过下面的链接下载最新版本的安装包: 9 | 10 | [![GitHub Release](https://img.shields.io/github/v/release/linuxsuren/api-testing)](https://github.com/LinuxSuRen/api-testing/releases/latest) 11 | 12 | | Package | GitHub | Mirror from DaoCloud | 13 | |---|---|---| 14 | | `atest-desktop.msi` | [link](https://github.com/LinuxSuRen/api-testing/releases/latest/download/atest-desktop.msi) | [link](https://files.m.daocloud.io/github.com/LinuxSuRen/api-testing/releases/latest/download/atest-desktop.msi) | 15 | | `atest-linux-amd64.tar.gz` | [link](https://github.com/LinuxSuRen/api-testing/releases/latest/download/atest-linux-amd64.tar.gz) | [link](https://files.m.daocloud.io/github.com/LinuxSuRen/api-testing/releases/latest/download/atest-linux-amd64.tar.gz) | 16 | | `atest-darwin-amd64.tar.gz` | [link](https://github.com/LinuxSuRen/api-testing/releases/latest/download/atest-darwin-amd64.tar.gz) | [link](https://files.m.daocloud.io/github.com/LinuxSuRen/api-testing/releases/latest/download/atest-darwin-amd64.tar.gz) | 17 | 18 | ## 通过工具下载 19 | 20 | [hd](https://github.com/LinuxSuRen/http-downloader) 是一个支持多线程下载的工具: 21 | 22 | ```shell 23 | hd i atest 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/tasks/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "任务" 3 | weight: 2 4 | description: 通过任务学习 API Testing 实践。 5 | --- 6 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/tasks/code-generator.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "代码生成" 3 | weight = 104 4 | +++ 5 | 6 | `atest` 支持把测试用例生成多种开发语言的代码: 7 | 8 | * curl 9 | * Java 10 | * Golang 11 | * Python 12 | * JavaScript 13 | * [Robot Framework](https://robotframework.org/) 14 | 15 | > 该功能需要在 Web UI 上使用。 16 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/tasks/job.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "任务" 3 | weight = 101 4 | +++ 5 | 6 | 在特定情况下,执行接口测试用例前需要执行相应的任务,例如:数据初始化、等待服务就绪等等。 `atest` 的任务功能,就是为了满足这类场景而设计的。 7 | 8 | > 任务的执行引擎为 [expr](https://expr.medv.io),如果当前页面给出的示例无法满足你的需求,可以查阅相关的官方文档。 9 | 10 | ## 等待接口响应码为 200 11 | 12 | 以下的例子会每隔一秒请求一次指定的接口,并检查响应码(Status Code)是否为 200,如果不是的话,则最多会重试 3 次: 13 | 14 | ```yaml 15 | name: demo 16 | api: http://localhost 17 | items: 18 | - name: login 19 | before: 20 | items: 21 | - httpReady("http://localhost/health", 3) 22 | request: 23 | api: /demo 24 | ``` 25 | 26 | 如果希望检查响应体的话,则可以用下面的表达式: 27 | 28 | ``` 29 | httpReady("http://localhost:17001/actuator/health", 3, 'components.discoveryComposite.components.eureka.details.applications["AUTH"] == 1') 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/tasks/mock/object.yaml: -------------------------------------------------------------------------------- 1 | #!api-testing-mock 2 | # yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-mock-schema.json 3 | objects: 4 | - name: projects 5 | initCount: 3 6 | sample: | 7 | { 8 | "name": "atest", 9 | "color": "{{ randEnum "blue" "read" "pink" }}" 10 | } 11 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/tasks/quickstart.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "快速入门" 3 | weight: 1 4 | description: 只需几个简单的步骤即可开始使用 API Testing。 5 | --- 6 | 7 | 本指南将帮助您通过几个简单的步骤开始使用 API Testing。 8 | 9 | ## 执行部分测试用例 10 | 11 | 下面的命令会执行名称中包含 `sbom` 的所有测试用例: 12 | 13 | ```shell 14 | atest run -p test-suite.yaml --case-filter sbom 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/tasks/secure.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "关于安全" 3 | weight = 8 4 | +++ 5 | 6 | 通常在不使用 TLS 证书认证时,gRPC 客户端与服务端之间进行的是明文通信,信息易被第三方监听或篡改。所以大多数情况下均推荐使用 SSL/TLS 保护 gRPC 服务。目前`atest`已实现服务端 TLS,双向 TLS(mTLS) 需等待后续实现。 7 | 8 | 默认情况下`atest`不使用任何安全策略,等价于`spec.secure.insecure = true`。启用 TLS 仅需 yaml 中添加以下内容: 9 | 10 | ```yaml 11 | spec: 12 | secure: 13 | cert: server.pem 14 | serverName: atest 15 | ``` 16 | 17 | ## 字段说明 18 | 19 | `secure`共有以下五个字段: 20 | 21 | | 字段名 | 类型 | 是否可选 | 22 | | ---------- | ------ | -------- | 23 | | cert | string | x | 24 | | ca | string | √ | 25 | | key | string | √ | 26 | | serverName | string | x | 27 | | insecure | bool | √ | 28 | 29 | `cert`为客户端需要配置的证书的文件路径,格式为`PEM`。 30 | 31 | `serverName`为 TLS 所需的服务名,通常为签发证书时使用的 x509 SAN。 32 | 33 | `ca`为 CA 证书的路径,`key`为与`cert`对应的私钥,这两项填写后代表启用 mTLS。(mTLS 尚未实现) 34 | 35 | 当`insecure`为`false`时,`cert`和`serverName`为必填项。 36 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/tasks/template.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "用例模板" 3 | weight = 100 4 | +++ 5 | 6 | `atest` 采用 [sprig](https://masterminds.github.io/sprig/) 作为测试用例的模板引擎。通过模板函数可以生成很多随机数据: 7 | 8 | ## 手机号 9 | 10 | 下面的代码可以生成 `182` 开头的手机号: 11 | 12 | ``` 13 | 182{{shuffle "09876543"}} 14 | ``` 15 | 16 | ## 带权重的随机枚举 17 | 18 | 下面的代码以 80% 的概率返回 `open`,以 20% 的概率返回 `closed`: 19 | 20 | ``` 21 | {{randWeightEnum (weightObject 4 "open") (weightObject 1 "closed")}} 22 | ``` 23 | 24 | ## 时间 25 | 26 | 下面的代码可以生成当前时间,并制定时间格式: 27 | 28 | ``` 29 | {{ now.Format "2006-01-02T15:04:05Z07:00" }} 30 | ``` 31 | 32 | 如果想要获取其他时间,则可以参考如下写法: 33 | 34 | ```gotemplate 35 | {{(now | date_modify "2h") | date "2006-01-02T15:04:05"}} 36 | ``` 37 | 38 | ## 环境变量 39 | 40 | 下面的代码可以获取环境变量 `SHELL` 的值,在需要使用一个全局变量的时候,可以使用这个模板函数: 41 | 42 | ``` 43 | {{ env "SHELL" }} 44 | ``` 45 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/tasks/testsuite.yaml: -------------------------------------------------------------------------------- 1 | #!api-testing 2 | # yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-schema.json 3 | name: SpringBoot 4 | api: | 5 | {{default "http://localhost:8080" (env "SERVER")}} 6 | items: 7 | - name: health 8 | request: 9 | api: /health 10 | -------------------------------------------------------------------------------- /docs/site/content/zh/latest/tasks/verify.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "测试用例验证" 3 | weight = 102 4 | +++ 5 | 6 | `atest` 采用 https://expr.medv.io 对 HTTP 请求响应的验证,比如:返回的数据列表长度验证、具体值的验证等等。下面给出一些例子: 7 | 8 | > 需要注意的是,`data` 指的是 HTTP Response Body(响应体)的 JSON 对象。 9 | 10 | ## 数组长度判断 11 | 12 | ```yaml 13 | - name: projectKinds 14 | request: 15 | api: /api/resources/projectKinds 16 | expect: 17 | verify: 18 | - len(data.data) == 6 19 | ``` 20 | 21 | ## 数组值检查 22 | 23 | ### 检查数组中是否有元素的字段包含特定值 24 | 25 | 示例数据: 26 | 27 | ```json 28 | { 29 | "data": [{ 30 | "key": "Content-Type" 31 | }] 32 | } 33 | ``` 34 | 35 | 校验配置: 36 | 37 | ```yaml 38 | - name: popularHeaders 39 | request: 40 | api: /popularHeaders 41 | expect: 42 | verify: 43 | - any(data.data, {.key == "Content-Type"}) 44 | ``` 45 | 46 | ### 检查数组中是否有元素的字段只包含特定值 47 | 48 | 校验配置: 49 | 50 | ```yaml 51 | - name: popularHeaders 52 | request: 53 | api: /popularHeaders 54 | expect: 55 | verify: 56 | - all(data.data, {.key == "Content-Type" or .key == "Target"}) 57 | ``` 58 | 59 | [更多用法](https://expr-lang.org/docs/language-definition#any). 60 | 61 | ## 字符串判断 62 | 63 | ```yaml 64 | - name: metrics 65 | request: 66 | api: | 67 | {{.param.server}}/metrics 68 | expect: 69 | verify: 70 | - indexOf(data, "atest_execution_count") != -1 71 | ``` 72 | 73 | [更多用法](https://expr-lang.org/docs/language-definition#indexOf). 74 | -------------------------------------------------------------------------------- /docs/site/content/zh/news/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "新闻" 3 | linktitle = "新闻" 4 | description = "有关 API Testing 的新闻" 5 | 6 | [[cascade]] 7 | type = "docs" 8 | +++ 9 | 10 | 这是**新闻**部分。它分为三个类别:博客、演讲和发布。 11 | 12 | 这些目录中的文件将按时间倒序列出。 13 | -------------------------------------------------------------------------------- /docs/site/content/zh/news/blogs/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "博客" 3 | description = "关于 API Testing 的博客" 4 | linktitle = "博客" 5 | 6 | [[cascade]] 7 | type = "docs" 8 | +++ 9 | -------------------------------------------------------------------------------- /docs/site/content/zh/news/presentations/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "演讲" 3 | description = "有关 API Testing 的演讲、讲座和活动" 4 | linktitle = "演讲" 5 | 6 | [[cascade]] 7 | type = "docs" 8 | +++ 9 | -------------------------------------------------------------------------------- /docs/site/content/zh/news/releases/_index.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "发布公告" 3 | description = "API Testing 发布公告" 4 | linktitle = "发布" 5 | 6 | [[cascade]] 7 | type = "docs" 8 | +++ 9 | 10 | 本文档提供了 API Testing 版本的详细信息。 11 | API Testing 遵循语义版本控制 [v2.0.0 规范](https://semver.org/)进行发布版本控制。 12 | 由于 API Testing 是一个新项目,因此次要版本是唯一被定义的版本。 13 | API Testing 维护人员在未来的某个日期将建立额外的发布详细信息,例如补丁版本。 14 | 15 | ## 稳定版本 {#stable-releases} 16 | 17 | 18 | 19 | ## 发布管理 {#release-management} 20 | 21 | 22 | 23 | ## 发布时间表 {#release-schedule} 24 | 25 | 26 | -------------------------------------------------------------------------------- /docs/site/content/zh/releases/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "版本发布" 3 | weight: 90 4 | description: 本节内容包含 API Testing 的版本概述。 5 | --- 6 | -------------------------------------------------------------------------------- /docs/site/content/zh/releases/release-note-v0.0.12.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "v0.0.12" 3 | +++ 4 | 5 | `atest` 版本发布 v0.0.12 6 | 7 | `atest` 是一款用 Golang 编写的、基于 YAML 格式的开源接口测试工具,可以方便地在本地、服务端、持续集成等场景中使用。 8 | 我们希望提供一个简单、强大、高质量的测试工具,方便测试、研发人员快速、低成本地借助接口测试为产品研发质量保驾护航。 9 | 10 | 通过以下命令启动 HTTP 代理服务器后,给您的浏览器配置该代理,打开业务系统就会自动录制: 11 | 12 | ```shell 13 | docker run -p 1234:8080 -v /var/tmp:/var/tmp \ 14 | ghcr.io/linuxsuren/api-testing atest-collector \ 15 | --filter-path /api \ 16 | -o /var/tmp/sample.yaml 17 | # --filter-path /api 会过滤所有以 /api 为前缀的 HTTP 请求 18 | # 关闭服务后,您可以在 /var/tmp/sample 这个目录中找到生成的测试用文件 19 | ``` 20 | 21 | ## 更新重点 22 | 23 | * 支持通过基于 HTTP 代理服务生成测试用例 24 | * 支持根据 Swagger 数据生成接口测试覆盖率 25 | * 增加 HTML、Markdown 等格式的测试报告 26 | * 代码重构,包括:包结构、原文件名整理,逻辑抽象为接口以及不同实现 27 | * 支持打印所有支持的模板函数 28 | * 优化 Kubernetes 的部署清单文件 29 | * 修复已知缺陷 30 | 31 | 本次版本发布,包含了以下三位 contributor 的努力: 32 | 33 | * [@LinuxSuRen](https://github.com/LinuxSuRen) 34 | * [@wongearl](https://github.com/wongearl) 35 | * [@yJunS](https://github.com/yJunS) 36 | 37 | ## 相关数据 38 | 39 | 下面是 `atest` 截止到 v0.0.12 的部分数据: 40 | 41 | * watch 3 42 | * fork 9 43 | * star 33 44 | * contributor 4 45 | * 二进制文件下载量 561 46 | * 代码行数 7.6k 47 | * 单元测试覆盖率 94% 48 | 49 | 想了解完整信息的话,请访问 https://github.com/LinuxSuRen/api-testing/releases/tag/v0.0.12 50 | -------------------------------------------------------------------------------- /docs/site/content/zh/releases/release-note-v0.0.14.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "v0.0.14" 3 | +++ 4 | 5 | `atest` 版本发布 `v0.0.14` 6 | 7 | `atest` 是一款用 Golang 编写的、开源的接口测试工具。 8 | 9 | 你可以在容器中启动: 10 | 11 | ```shell 12 | docker run --network host \ 13 | linuxsuren/api-testing:v0.0.14 14 | ``` 15 | 16 | 或者,直接[下载二进制文件](https://github.com/LinuxSuRen/api-testing/releases/tag/v0.0.14)后启动: 17 | 18 | ```shell 19 | atest server --local-storage /var/www/sample 20 | ``` 21 | 22 | ## 主要的新功能 23 | 24 | * 增加了对 `tRPC` 和 `gRPC` 协议的(命令行与 Web 界面)支持 25 | * 新增了 Helm Chart 的安装方式 26 | * 支持通过按钮切换暗模式 27 | * 支持启动启动插件 28 | * 支持在 Web 界面中参数化执行 29 | * 支持生成 `curl` 与 `Golang` 代码 30 | * 支持从 Postman 中导入测试用例 31 | * 可观测方便,增加了对 Apache SkyWalking 和 Prometheus 的支持 32 | * 一些 Web 界面操作的优化(例如:多语言、测试结果缓存、自动保存) 33 | 34 | 本次版本发布,包含了以下 5 位 contributor 的努力: 35 | 36 | * [@Ink-33](https://github.com/Ink-33) 37 | * [@LinuxSuRen](https://github.com/LinuxSuRen) 38 | * [@hellojukay](https://github.com/hellojukay) 39 | * [@kuv2707](https://github.com/kuv2707) 40 | * [@yuluo-yx](https://github.com/yuluo-yx) 41 | 42 | ## 相关数据 43 | 44 | 下面是 `atest` 截止到 `v0.0.14` 的部分数据: 45 | 46 | * watch 7 47 | * fork 23 48 | * star 104 49 | * contributor 12 50 | * 二进制文件下载量 1.1k 51 | * 代码行数 45k 52 | * 单元测试覆盖率 88% 53 | 54 | 想了解完整信息的话,请访问 https://github.com/LinuxSuRen/api-testing/releases/tag/v0.0.14 55 | -------------------------------------------------------------------------------- /docs/site/content/zh/releases/release-note-v0.0.15.md: -------------------------------------------------------------------------------- 1 | +++ 2 | title = "v0.0.15" 3 | +++ 4 | 5 | `atest` 发布 `v0.0.15` 6 | 7 | `atest` 是致力于帮助开发者持续保持高质量 API 的开源接口工具。 8 | 9 | 你可以在命令行终端或者容器中启动: 10 | 11 | ```shell 12 | docker run -p 8080:8080 linuxsuren/api-testing:v0.0.15 13 | ``` 14 | 15 | ## 亮点 16 | 17 | 在本次版本发布之前,成功地为以下开源项目实现了 API 的 E2E 测试: 18 | 19 | * [halo-dev/halo](https://github.com/halo-dev/halo/pull/4892),一款 Java 实现的开源建站工具 20 | * [dromara/hertzbeat](https://github.com/dromara/hertzbeat/pull/1387),一款监控系统 21 | 22 | 非常期待 `atest` 可以帮助更多的项目持续提升、保持 API 稳定性。 23 | 24 | ## 主要的新功能 25 | 26 | * 支持复用 Cookies(简化了基于 Cookie 做会话认证) (#301) @LinuxSuRen 27 | * 增加了基于 Docker 的应用性能监控 (#300) @LinuxSuRen 28 | * 支持以 Comment 的方式发送测试报告到 GitHub PR (#298) @LinuxSuRen 29 | * UI 布局重构 (#297) @LinuxSuRen 30 | * 增加对 OAuth 认证的支持(包括 Device 模式) (#290) @LinuxSuRen 31 | * 支持设置 gRPC 的元数据 (#282) @LinuxSuRen 32 | * 增加了新的后端存储: Mongodb (#278) @LinuxSuRen 33 | 34 | ## 致谢 35 | 36 | 本次版本发布,包含了以下 2 位 contributor 的努力: 37 | 38 | * [@im-jinxinwang](https://github.com/im-jinxinwang) 39 | * [@LinuxSuRen](https://github.com/LinuxSuRen) 40 | 41 | ## 相关数据 42 | 43 | 下面是 `atest` 截止到 `v0.0.15` 的部分数据: 44 | 45 | * watch 7 46 | * fork 23 47 | * star 123 (+19) 48 | * contributor 13 (+1) 49 | * 二进制文件下载量 1.3k (+0.2k) 50 | * 部分镜像 2.2k 51 | * 单元测试覆盖率 82% (-6%) 52 | 53 | 想了解完整信息的话,请访问 https://github.com/LinuxSuRen/api-testing/releases/tag/v0.0.15 54 | -------------------------------------------------------------------------------- /docs/site/content/zh/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 搜索结果 3 | layout: search 4 | --- 5 | -------------------------------------------------------------------------------- /docs/site/data/adopters.yaml: -------------------------------------------------------------------------------- 1 | adopters: 2 | # todo 3 | -------------------------------------------------------------------------------- /docs/site/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | services: 4 | 5 | site: 6 | image: docsy/docsy-example 7 | build: 8 | context: . 9 | command: server 10 | ports: 11 | - "1313:1313" 12 | volumes: 13 | - .:/src 14 | -------------------------------------------------------------------------------- /docs/site/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/google/docsy-example 2 | 3 | go 1.22.1 4 | 5 | require ( 6 | github.com/FortAwesome/Font-Awesome v0.0.0-20230327165841-0698449d50f2 // indirect 7 | github.com/google/docsy v0.7.1 // indirect 8 | github.com/twbs/bootstrap v5.2.3+incompatible // indirect 9 | ) 10 | -------------------------------------------------------------------------------- /docs/site/layouts/404.html: -------------------------------------------------------------------------------- 1 | {{ define "main" -}} 2 |
3 |

Not found

4 |

Oops! This page doesn't exist. Try going back to the home page.

5 |
6 | {{- end }} 7 | -------------------------------------------------------------------------------- /docs/site/static/favicons/favicons.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/docs/site/static/favicons/favicons.ico -------------------------------------------------------------------------------- /docs/site/static/favicons/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /docs/site/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/docs/site/static/img/logo.png -------------------------------------------------------------------------------- /docs/site/static/logos/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/docs/site/static/logos/logo.png -------------------------------------------------------------------------------- /e2e/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/linuxsuren/api-testing:master 2 | 3 | WORKDIR /workspace 4 | COPY e2e/* . 5 | COPY helm/api-testing api-testing 6 | RUN apk add curl openssh-client bash openssl 7 | RUN curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 8 | RUN chmod 700 get_helm.sh 9 | RUN ./get_helm.sh 10 | RUN chmod +x entrypoint.sh 11 | RUN chmod +x k8s.sh 12 | 13 | CMD [ "/workspace/entrypoint.sh" ] 14 | -------------------------------------------------------------------------------- /e2e/README.md: -------------------------------------------------------------------------------- 1 | You can build the image locally in the repository root directory: 2 | 3 | If you are a Linux/MacOS user, you can use the following command: 4 | ```shell 5 | REGISTRY=ghcr.io TAG=master make image 6 | ``` 7 | 8 | If you are a Windows user, you can use the following command: 9 | ```powershell 10 | Set-Content -Path "env:REGISTRY" -Value "ghcr.io" 11 | Set-Content -Path "env:TAG" -Value "master" 12 | make image 13 | ``` 14 | -------------------------------------------------------------------------------- /e2e/code-generator/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG LAN_ENV=docker.io/library/golang:1.21 2 | 3 | FROM ghcr.io/linuxsuren/api-testing:master AS atest 4 | FROM ghcr.io/linuxsuren/hd:v0.0.42 as downloader 5 | RUN hd install jq 6 | FROM $LAN_ENV 7 | 8 | WORKDIR /workspace 9 | COPY . . 10 | COPY --from=downloader /usr/local/bin/jq /usr/local/bin/jq 11 | COPY --from=atest /usr/local/bin/atest /usr/local/bin/atest 12 | 13 | CMD [ "/workspace/entrypoint.sh" ] 14 | -------------------------------------------------------------------------------- /e2e/code-generator/JavaScript.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export sourcefile=$1 5 | # exit if no source file is specified 6 | if [ -z "$sourcefile" ] 7 | then 8 | echo "no source file is specified" 9 | exit 1 10 | fi 11 | 12 | mv ${sourcefile} main.js 13 | node main.js 14 | -------------------------------------------------------------------------------- /e2e/code-generator/compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | golang: 3 | build: 4 | context: . 5 | dockerfile: Dockerfile 6 | args: 7 | - LAN_ENV=docker.io/library/golang:1.21 8 | command: 9 | - /workspace/entrypoint.sh 10 | - golang 11 | java: 12 | build: 13 | context: . 14 | dockerfile: Dockerfile 15 | args: 16 | - LAN_ENV=docker.io/library/openjdk:23 17 | command: 18 | - /workspace/entrypoint.sh 19 | - java 20 | python: 21 | build: 22 | context: . 23 | dockerfile: Dockerfile 24 | args: 25 | - LAN_ENV=docker.io/library/python:3.8 26 | command: 27 | - /workspace/entrypoint.sh 28 | - python 29 | robot-framework: 30 | build: 31 | context: . 32 | dockerfile: Dockerfile 33 | args: 34 | - LAN_ENV=docker.io/library/python:3.8 35 | command: 36 | - /workspace/entrypoint.sh 37 | - robot-framework 38 | javascript: 39 | build: 40 | context: . 41 | dockerfile: Dockerfile 42 | args: 43 | - LAN_ENV=docker.io/library/node:22 44 | command: 45 | - /workspace/entrypoint.sh 46 | - JavaScript 47 | curl: 48 | build: 49 | context: . 50 | dockerfile: Dockerfile 51 | args: 52 | - LAN_ENV=docker.io/library/openjdk:23 53 | command: 54 | - /workspace/entrypoint.sh 55 | - curl 56 | -------------------------------------------------------------------------------- /e2e/code-generator/curl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export sourcefile=$1 5 | # exit if no source file is specified 6 | if [ -z "$sourcefile" ] 7 | then 8 | echo "no source file is specified" 9 | exit 1 10 | fi 11 | 12 | mv ${sourcefile} main.sh 13 | sh main.sh 14 | -------------------------------------------------------------------------------- /e2e/code-generator/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export lang=$1 5 | # exit if no language is specified 6 | if [ -z "$lang" ] 7 | then 8 | echo "no language is specified" 9 | exit 1 10 | fi 11 | 12 | mkdir -p /root/.config/atest 13 | mkdir -p /var/data 14 | 15 | nohup atest server --local-storage '/workspace/test-suites/*.yaml'& 16 | sleep 1 17 | 18 | # test_cases=("postRequest" "requestWithHeader" "requestWithoutHeader") 19 | test_cases=("requestWithHeader" "requestWithoutHeader") 20 | 21 | for test_case in "${test_cases[@]}" 22 | do 23 | curl http://localhost:8080/api/v1/codeGenerators/generate -X POST \ 24 | -d '{"TestSuite": "test", "TestCase": "'"${test_case}"'", "Generator": "'"$lang"'"}' > code.json 25 | 26 | cat code.json | jq .message -r | sed 's/\\n/\n/g' | sed 's/\\t/\t/g' | sed 's/\\\"/"/g' > code.txt 27 | cat code.txt 28 | 29 | sh /workspace/${lang}.sh code.txt 30 | done 31 | 32 | exit 0 33 | -------------------------------------------------------------------------------- /e2e/code-generator/golang.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export sourcefile=$1 5 | # exit if no source file is specified 6 | if [ -z "$sourcefile" ] 7 | then 8 | echo "no source file is specified" 9 | exit 1 10 | fi 11 | 12 | mv ${sourcefile} main.go 13 | go run main.go 14 | -------------------------------------------------------------------------------- /e2e/code-generator/java.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export sourcefile=$1 5 | # exit if no source file is specified 6 | if [ -z "$sourcefile" ] 7 | then 8 | echo "no source file is specified" 9 | exit 1 10 | fi 11 | 12 | mv ${sourcefile} Main.java 13 | java Main.java 14 | -------------------------------------------------------------------------------- /e2e/code-generator/python.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export sourcefile=$1 5 | # exit if no source file is specified 6 | if [ -z "$sourcefile" ] 7 | then 8 | echo "no source file is specified" 9 | exit 1 10 | fi 11 | 12 | mv ${sourcefile} main.py 13 | pip install requests 14 | python main.py 15 | -------------------------------------------------------------------------------- /e2e/code-generator/robot-framework.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export sourcefile=$1 5 | # exit if no source file is specified 6 | if [ -z "$sourcefile" ] 7 | then 8 | echo "no source file is specified" 9 | exit 1 10 | fi 11 | 12 | mv ${sourcefile} test.robot 13 | pip install robotframework robotframework-requests 14 | robot test.robot 15 | -------------------------------------------------------------------------------- /e2e/code-generator/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | docker compose version 5 | 6 | targets=(golang java python javascript curl robot-framework) 7 | for target in "${targets[@]}" 8 | do 9 | docker compose down 10 | docker compose up --build $target --exit-code-from $target 11 | done 12 | -------------------------------------------------------------------------------- /e2e/code-generator/test-suites/test-suite.yaml: -------------------------------------------------------------------------------- 1 | #!api-testing 2 | # yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-schema.json 3 | name: test 4 | api: http://localhost:8080/api/v1 5 | param: 6 | suiteName: test 7 | caseName: test 8 | items: 9 | - name: postRequest 10 | request: 11 | api: /suites 12 | method: POST 13 | body: | 14 | { 15 | "name": "hello", 16 | "api": "http://localhost:8080/api/v1" 17 | } 18 | - name: requestWithHeader 19 | request: 20 | api: /suites 21 | header: 22 | auth: fake 23 | - name: requestWithoutHeader 24 | request: 25 | api: /suites 26 | -------------------------------------------------------------------------------- /e2e/compose-external.yaml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | services: 3 | testing: 4 | image: ghcr.io/linuxsuren/api-testing:master 5 | command: ["atest", "run", "-p=/workspace/e2e/test-suite.yaml"] 6 | pull_policy: never 7 | environment: 8 | SERVER: http://server:8080 9 | volumes: 10 | - type: volume 11 | source: cache 12 | target: /workspace/e2e 13 | depends_on: 14 | server: 15 | condition: service_healthy 16 | links: 17 | - server 18 | server: 19 | image: ghcr.io/devops-ws/learn-springboot:master 20 | healthcheck: 21 | test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/8080"] 22 | interval: 3s 23 | timeout: 60s 24 | retries: 10 25 | start_period: 3s 26 | volumes: 27 | - type: volume 28 | source: cache 29 | target: /workspace/e2e 30 | 31 | volumes: 32 | cache: 33 | -------------------------------------------------------------------------------- /e2e/git.yaml: -------------------------------------------------------------------------------- 1 | #!api-testing 2 | # yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-schema.json 3 | # https://docs.gitlab.com/ee/api/api_resources.html 4 | name: atest 5 | api: | 6 | {{default "http://localhost:8080" (env "SERVER")}}/server.Runner 7 | param: 8 | server: | 9 | {{default "http://localhost:8080" (env "SERVER")}} 10 | items: 11 | - name: healthz 12 | before: 13 | items: 14 | - httpReady("{{.param.server}}/healthz", 6000) 15 | request: 16 | api: | 17 | {{default "http://localhost:8080" (env "SERVER")}}/healthz 18 | - name: CreateStore 19 | request: 20 | api: /CreateStore 21 | method: POST 22 | body: | 23 | { 24 | "name": "git", 25 | "url": "https://gitee.com/linuxsuren/api-testing-hub", 26 | "kind": { 27 | "name": "atest-store-git" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /e2e/k8s.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | sleep 6 5 | echo "Running k8s.sh" 6 | 7 | ls -hal 8 | cd api-testing 9 | echo "build helm dependency" 10 | helm dependency build 11 | 12 | echo "install helm chart" 13 | helm install --kube-apiserver https://server:6443 --kube-token abcd --kube-insecure-skip-tls-verify \ 14 | api-testing . \ 15 | --set service.type=NodePort \ 16 | --set service.nodePort=30000 \ 17 | --set persistence.enabled=false \ 18 | --set image.registry=ghcr.io \ 19 | --set image.repository=linuxsuren/api-testing \ 20 | --set image.tag=master \ 21 | --set extension.registry=ghcr.io 22 | 23 | SERVER=http://server:30000 atest run -p git.yaml 24 | -------------------------------------------------------------------------------- /e2e/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | file=$1 4 | if [ "$file" == "" ] 5 | then 6 | file=compose.yaml 7 | fi 8 | 9 | docker compose version 10 | docker compose -f "$file" down 11 | docker compose -f "$file" up --build testing --exit-code-from testing --remove-orphans 12 | -------------------------------------------------------------------------------- /helm/api-testing/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /helm/api-testing/Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: mongodb 3 | repository: oci://registry-1.docker.io/bitnamicharts 4 | version: 15.1.7 5 | digest: sha256:e573c76d3c75c7e5bc61cbf1e7de46bbf59837de68ac06ebdfe1fa32337a6f58 6 | generated: "2024-05-09T11:36:47.7429098+08:00" 7 | -------------------------------------------------------------------------------- /helm/api-testing/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: api-testing 3 | description: YAML based API testing tool 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: v0.0.4 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "v0.0.15" 25 | 26 | dependencies: 27 | - name: mongodb 28 | version: ^15.0.1 29 | repository: oci://registry-1.docker.io/bitnamicharts 30 | condition: mongodb.enabled 31 | -------------------------------------------------------------------------------- /helm/api-testing/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "api-testing.fullname" . }} 6 | labels: 7 | {{- include "api-testing.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "api-testing.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | target: 21 | type: Utilization 22 | averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 23 | {{- end }} 24 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 25 | - type: Resource 26 | resource: 27 | name: memory 28 | target: 29 | type: Utilization 30 | averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /helm/api-testing/templates/pvc.yaml: -------------------------------------------------------------------------------- 1 | {{- $core := .Values.persistence.persistentVolumeClaim.core -}} 2 | {{- if and .Values.persistence.enabled (not $core.existingClaim) }} 3 | kind: PersistentVolumeClaim 4 | apiVersion: v1 5 | metadata: 6 | name: {{ include "api-testing.fullname" . }} 7 | labels: 8 | {{- include "api-testing.labels" . | nindent 4 }} 9 | spec: 10 | accessModes: 11 | - {{ $core.accessMode }} 12 | resources: 13 | requests: 14 | storage: {{ $core.size }} 15 | {{- if $core.storageClass }} 16 | {{- if eq "-" $core.storageClass }} 17 | storageClassName: "" 18 | {{- else }} 19 | storageClassName: {{ $core.storageClass }} 20 | {{- end }} 21 | {{- end }} 22 | volumeMode: {{ $core.volumeMode }} 23 | {{- end }} 24 | -------------------------------------------------------------------------------- /helm/api-testing/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "api-testing.fullname" . }} 5 | labels: 6 | {{- include "api-testing.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | {{- if and .Values.service.nodePort }} 15 | nodePort: {{ .Values.service.nodePort }} 16 | {{- end}} 17 | selector: 18 | {{- include "api-testing.selectorLabels" . | nindent 4 }} 19 | -------------------------------------------------------------------------------- /helm/api-testing/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "api-testing.serviceAccountName" . }} 6 | labels: 7 | {{- include "api-testing.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /helm/api-testing/templates/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceMonitor.enabled }} 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | name: {{ include "api-testing.fullname" . }}-servicemonitor 6 | labels: 7 | {{- include "api-testing.labels" . | nindent 4 }} 8 | spec: 9 | selector: 10 | matchLabels: 11 | {{- include "api-testing.selectorLabels" . | nindent 6 }} 12 | endpoints: 13 | - port: http 14 | interval: {{ .Values.serviceMonitor.interval }} 15 | path: /metrics 16 | {{- end }} -------------------------------------------------------------------------------- /helm/api-testing/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "api-testing.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "api-testing.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "api-testing.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "embed" 5 | "os" 6 | 7 | "github.com/linuxsuren/api-testing/pkg/version" 8 | 9 | "github.com/linuxsuren/api-testing/cmd" 10 | "github.com/linuxsuren/api-testing/pkg/server" 11 | exec "github.com/linuxsuren/go-fake-runtime" 12 | ) 13 | 14 | func main() { 15 | version.SetMod(goMod) 16 | c := cmd.NewRootCmd(exec.NewDefaultExecer(), server.NewDefaultHTTPServer()) 17 | if err := c.Execute(); err != nil { 18 | os.Exit(1) 19 | } 20 | } 21 | 22 | //go:embed go.mod 23 | var goMod string 24 | -------------------------------------------------------------------------------- /pkg/apispec/data/proto/google/api/annotations.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/api/http.proto"; 20 | import "google/protobuf/descriptor.proto"; 21 | 22 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 23 | option java_multiple_files = true; 24 | option java_outer_classname = "AnnotationsProto"; 25 | option java_package = "com.google.api"; 26 | option objc_class_prefix = "GAPI"; 27 | 28 | extend google.protobuf.MethodOptions { 29 | // See `HttpRule`. 30 | HttpRule http = 72295728; 31 | } -------------------------------------------------------------------------------- /pkg/apispec/data/proto/google/protobuf/annotations.proto: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/pkg/apispec/data/proto/google/protobuf/annotations.proto -------------------------------------------------------------------------------- /pkg/apispec/fake.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package apispec 18 | 19 | type fakeAPISpec struct { 20 | apis [][]string 21 | } 22 | 23 | // NewFakeAPISpec creates a new instance of fakeAPISpec 24 | func NewFakeAPISpec(apis [][]string) APICoverage { 25 | return &fakeAPISpec{apis: apis} 26 | } 27 | 28 | // HaveAPI is fake method 29 | func (f *fakeAPISpec) HaveAPI(path, method string) (exist bool) { 30 | for _, item := range f.apis { 31 | if len(item) >= 2 && item[0] == path && item[1] == method { 32 | exist = true 33 | break 34 | } 35 | } 36 | return 37 | } 38 | 39 | // APICount is fake method 40 | func (f *fakeAPISpec) APICount() (count int) { 41 | count = len(f.apis) 42 | return 43 | } 44 | -------------------------------------------------------------------------------- /pkg/apispec/grpc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package apispec 18 | 19 | import ( 20 | "embed" 21 | "io/fs" 22 | "strings" 23 | ) 24 | 25 | //go:embed data/proto 26 | var res embed.FS 27 | 28 | func GetProtoFiles() (files map[string]string, err error) { 29 | efs := &res 30 | files = make(map[string]string) 31 | if err := fs.WalkDir(efs, ".", func(path string, d fs.DirEntry, err error) error { 32 | if d.IsDir() { 33 | return nil 34 | } 35 | 36 | var data []byte 37 | if data, err = fs.ReadFile(efs, path); err == nil { 38 | files[strings.TrimPrefix(path, "data/proto/")] = string(data) 39 | } else { 40 | return err 41 | } 42 | return nil 43 | }); err != nil { 44 | return nil, err 45 | } 46 | 47 | return files, nil 48 | } 49 | -------------------------------------------------------------------------------- /pkg/apispec/grpc_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package apispec 18 | 19 | import ( 20 | "strings" 21 | "testing" 22 | 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | func TestFindProto(t *testing.T) { 27 | files, err := GetProtoFiles() 28 | assert.NoError(t, err) 29 | for file := range files { 30 | if !strings.HasPrefix(file, "google") && 31 | !strings.HasPrefix(file, "protoc-gen-openapiv2") && 32 | !strings.HasPrefix(file, "validate") { 33 | t.Fatal("unknown file path") 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /pkg/apispec/testdata/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "sample", 5 | "title": "sample", 6 | "version": "1.0.0" 7 | }, 8 | "paths": { 9 | "/api/v1/users": { 10 | "get": { 11 | "summary": "summary", 12 | "operationId": "getUsers" 13 | }, 14 | "post": { 15 | "summary": "summary", 16 | "operationId": "createUser" 17 | } 18 | }, 19 | "/api/v1/users/{user}": { 20 | "get": { 21 | "summary": "summary", 22 | "operationId": "getUser" 23 | }, 24 | "delete": { 25 | "summary": "summary", 26 | "operationId": "deleteUser" 27 | }, 28 | "put": { 29 | "summary": "summary", 30 | "operationId": "updateUser" 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /pkg/compare/error_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package compare 18 | 19 | import ( 20 | "fmt" 21 | "testing" 22 | 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | func TestNewNoEqualErr(t *testing.T) { 27 | err := newNoEqualErr("data", fmt.Errorf("this is msg")) 28 | err = newNoEqualErr("to", err) 29 | err = newNoEqualErr("path", err) 30 | assert.Equal(t, "compare: field path.to.data: this is msg", err.Error()) 31 | } 32 | -------------------------------------------------------------------------------- /pkg/extension/pprof.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package extension 17 | 18 | import ( 19 | "bytes" 20 | "runtime/pprof" 21 | ) 22 | 23 | func LoadPProf(name string) []byte { 24 | buf := new(bytes.Buffer) 25 | if p := pprof.Lookup(name); p != nil { 26 | p.WriteTo(buf, 0) 27 | } 28 | return buf.Bytes() 29 | } 30 | -------------------------------------------------------------------------------- /pkg/extension/signal.go: -------------------------------------------------------------------------------- 1 | package extension 2 | 3 | import ( 4 | "context" 5 | "os" 6 | "os/signal" 7 | "syscall" 8 | 9 | "github.com/linuxsuren/api-testing/pkg/logging" 10 | ) 11 | 12 | var ( 13 | signalLogger = logging.DefaultLogger(logging.LogLevelInfo).WithName("signal") 14 | ) 15 | 16 | type StopAble interface { 17 | Stop() 18 | } 19 | 20 | func RegisterStopSignal(ctx context.Context, callback func(), servers ...StopAble) { 21 | endChan := make(chan os.Signal, 1) 22 | signal.Notify(endChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT) 23 | go func(ctx context.Context) { 24 | select { 25 | case <-endChan: 26 | case <-ctx.Done(): 27 | } 28 | if callback != nil { 29 | callback() 30 | } 31 | for _, server := range servers { 32 | signalLogger.Info("Stopping the server...") 33 | server.Stop() 34 | } 35 | }(ctx) 36 | } 37 | -------------------------------------------------------------------------------- /pkg/extension/singal_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package extension 17 | 18 | import ( 19 | "context" 20 | "testing" 21 | "time" 22 | 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | func TestRegisterStopSignal(t *testing.T) { 27 | var stoppedA bool 28 | fs := &fakeServer{} 29 | ctx, cancel := context.WithTimeout(context.TODO(), time.Second) 30 | cancel() 31 | RegisterStopSignal(ctx, func() { 32 | stoppedA = true 33 | }, fs) 34 | time.Sleep(time.Second * 2) 35 | assert.True(t, stoppedA) 36 | assert.True(t, fs.signal) 37 | } 38 | 39 | type fakeServer struct { 40 | signal bool 41 | } 42 | 43 | func (s *fakeServer) Stop() { 44 | s.signal = true 45 | } 46 | -------------------------------------------------------------------------------- /pkg/generator/converter_raw.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package generator 17 | 18 | import ( 19 | "github.com/linuxsuren/api-testing/pkg/testing" 20 | "gopkg.in/yaml.v3" 21 | ) 22 | 23 | type rawConverter struct { 24 | } 25 | 26 | func init() { 27 | RegisterTestSuiteConverter("raw", &rawConverter{}) 28 | } 29 | 30 | func (c *rawConverter) Convert(testSuite *testing.TestSuite) (result string, err error) { 31 | if err = testSuite.Render(make(map[string]interface{})); err == nil { 32 | for _, item := range testSuite.Items { 33 | item.Request.RenderAPI(testSuite.API) 34 | } 35 | 36 | var data []byte 37 | if data, err = yaml.Marshal(testSuite); err == nil { 38 | result = string(data) 39 | } 40 | } 41 | return 42 | } 43 | -------------------------------------------------------------------------------- /pkg/generator/converter_raw_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package generator 17 | 18 | import ( 19 | "testing" 20 | 21 | _ "embed" 22 | 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | func TestRawConvert(t *testing.T) { 27 | rawConvert := GetTestSuiteConverter("raw") 28 | assert.NotNil(t, rawConvert) 29 | 30 | output, err := rawConvert.Convert(createTestSuiteForTest()) 31 | assert.NoError(t, err) 32 | assert.Equal(t, expectedTestSuite, output) 33 | } 34 | 35 | //go:embed testdata/expected_testsuite.yaml 36 | var expectedTestSuite string 37 | -------------------------------------------------------------------------------- /pkg/generator/data/curl.tpl: -------------------------------------------------------------------------------- 1 | curl -k -X {{.Request.Method}} '{{.Request.API}}' \ 2 | {{- range $key, $val := .Request.Header}} 3 | -H '{{$key}}: {{$val}}' \ 4 | {{- end}} 5 | {{- if .Request.Body.String }} 6 | --data-raw '{{.Request.Body.String}}' 7 | {{- end}} 8 | -------------------------------------------------------------------------------- /pkg/generator/data/robot-suite.tpl: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Library RequestsLibrary 3 | 4 | *** Test Cases *** 5 | {{- range $item := .Items}} 6 | {{$item.Name}} 7 | {{- if $item.Request.Header}} 8 | ${headers}= Create Dictionary {{- range $key, $val := $item.Request.Header}} {{$key}} {{$val}}{{- end}} 9 | {{- end}} 10 | ${response}= {{$item.Request.Method}} {{$item.Request.API}}{{- if .Request.Header}} headers=${headers}{{end}} 11 | {{- end}} 12 | -------------------------------------------------------------------------------- /pkg/generator/data/robot.tpl: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Library RequestsLibrary 3 | 4 | *** Test Cases *** 5 | {{.Name}} 6 | {{- if .Request.Header}} 7 | ${headers}= Create Dictionary {{- range $key, $val := .Request.Header}} {{$key}} {{$val}}{{- end}} 8 | {{- end}} 9 | ${response}= {{.Request.Method}} {{.Request.API}}{{- if .Request.Header}} headers=${headers}{{end}} 10 | -------------------------------------------------------------------------------- /pkg/generator/helper.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package generator 17 | 18 | import ( 19 | "html/template" 20 | ) 21 | 22 | func safeString(str string) template.HTML { 23 | return template.HTML(str) 24 | } 25 | -------------------------------------------------------------------------------- /pkg/generator/javascript_generator.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package generator 17 | 18 | import ( 19 | _ "embed" 20 | 21 | "github.com/linuxsuren/api-testing/pkg/testing" 22 | ) 23 | 24 | type javascriptGenerator struct { 25 | } 26 | 27 | func NewJavaScriptGenerator() CodeGenerator { 28 | return &javascriptGenerator{} 29 | } 30 | 31 | func (g *javascriptGenerator) Generate(testSuite *testing.TestSuite, testcase *testing.TestCase) (string, error) { 32 | return generate(testSuite, testcase, "javascript template", javascriptTemplate) 33 | } 34 | 35 | func init() { 36 | RegisterCodeGenerator("JavaScript", NewJavaScriptGenerator()) 37 | } 38 | 39 | //go:embed data/main.javascript.tpl 40 | var javascriptTemplate string 41 | -------------------------------------------------------------------------------- /pkg/generator/python_generator.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package generator 17 | 18 | import ( 19 | _ "embed" 20 | 21 | "github.com/linuxsuren/api-testing/pkg/testing" 22 | ) 23 | 24 | type pythonGenerator struct { 25 | } 26 | 27 | func NewPythonGenerator() CodeGenerator { 28 | return &pythonGenerator{} 29 | } 30 | 31 | func (g *pythonGenerator) Generate(testSuite *testing.TestSuite, testcase *testing.TestCase) (result string, err error) { 32 | return generate(testSuite, testcase, "python template", pythonTemplate) 33 | } 34 | 35 | func init() { 36 | RegisterCodeGenerator("python", NewPythonGenerator()) 37 | } 38 | 39 | //go:embed data/main.python.tpl 40 | var pythonTemplate string 41 | -------------------------------------------------------------------------------- /pkg/generator/robot_generator.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package generator 17 | 18 | import ( 19 | _ "embed" 20 | 21 | "github.com/linuxsuren/api-testing/pkg/testing" 22 | ) 23 | 24 | type robotGenerator struct { 25 | } 26 | 27 | func NewRobotGenerator() CodeGenerator { 28 | return &robotGenerator{} 29 | } 30 | 31 | func (g *robotGenerator) Generate(testSuite *testing.TestSuite, testcase *testing.TestCase) (string, error) { 32 | tpl := robotTemplate 33 | if testcase == nil { 34 | tpl = robotSuiteTemplate 35 | } 36 | return generate(testSuite, testcase, "robot-framework", tpl) 37 | } 38 | 39 | func init() { 40 | RegisterCodeGenerator("robot-framework", NewRobotGenerator()) 41 | } 42 | 43 | //go:embed data/robot.tpl 44 | var robotTemplate string 45 | 46 | //go:embed data/robot-suite.tpl 47 | var robotSuiteTemplate string 48 | -------------------------------------------------------------------------------- /pkg/generator/testdata/expected_go_body_request_code.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | package main 14 | 15 | import ( 16 | "bytes" 17 | "io" 18 | "net/http" 19 | ) 20 | 21 | func main() { 22 | body := bytes.NewBufferString(`{"key": "value"}`) 23 | 24 | req, err := http.NewRequest("GET", "https://www.baidu.com", body) 25 | if err != nil { 26 | panic(err) 27 | } 28 | req.Header.Set("User-Agent", "atest") 29 | 30 | resp, err := http.DefaultClient.Do(req) 31 | if err != nil { 32 | panic(err) 33 | } 34 | 35 | if resp.StatusCode != http.StatusOK { 36 | panic("status code is not 200") 37 | } 38 | 39 | data, err := io.ReadAll(resp.Body) 40 | println(string(data)) 41 | } 42 | -------------------------------------------------------------------------------- /pkg/generator/testdata/expected_go_code.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | package main 14 | 15 | import ( 16 | "bytes" 17 | "io" 18 | "net/http" 19 | ) 20 | 21 | func main() { 22 | body := bytes.NewBufferString(``) 23 | 24 | req, err := http.NewRequest("GET", "https://www.baidu.com", body) 25 | if err != nil { 26 | panic(err) 27 | } 28 | req.Header.Set("User-Agent", "atest") 29 | 30 | resp, err := http.DefaultClient.Do(req) 31 | if err != nil { 32 | panic(err) 33 | } 34 | 35 | if resp.StatusCode != http.StatusOK { 36 | panic("status code is not 200") 37 | } 38 | 39 | data, err := io.ReadAll(resp.Body) 40 | println(string(data)) 41 | } 42 | -------------------------------------------------------------------------------- /pkg/generator/testdata/expected_go_cookie_request_code.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | package main 14 | 15 | import ( 16 | "io" 17 | "net/http" 18 | ) 19 | 20 | func main() { 21 | data := url.Values{} 22 | data.Set("key", "value") 23 | body := strings.NewReader(data.Encode()) 24 | 25 | req, err := http.NewRequest("GET", "https://www.baidu.com", body) 26 | if err != nil { 27 | panic(err) 28 | } 29 | req.Header.Set("User-Agent", "atest") 30 | req.AddCookie(&http.Cookie{ 31 | Name: "name", 32 | Value: "value", 33 | }) 34 | 35 | resp, err := http.DefaultClient.Do(req) 36 | if err != nil { 37 | panic(err) 38 | } 39 | 40 | if resp.StatusCode != http.StatusOK { 41 | panic("status code is not 200") 42 | } 43 | 44 | data, err := io.ReadAll(resp.Body) 45 | println(string(data)) 46 | } 47 | -------------------------------------------------------------------------------- /pkg/generator/testdata/expected_go_form_request_code.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | package main 14 | 15 | import ( 16 | "io" 17 | "net/http" 18 | ) 19 | 20 | func main() { 21 | data := url.Values{} 22 | data.Set("key", "value") 23 | body := strings.NewReader(data.Encode()) 24 | 25 | req, err := http.NewRequest("GET", "https://www.baidu.com", body) 26 | if err != nil { 27 | panic(err) 28 | } 29 | req.Header.Set("User-Agent", "atest") 30 | 31 | resp, err := http.DefaultClient.Do(req) 32 | if err != nil { 33 | panic(err) 34 | } 35 | 36 | if resp.StatusCode != http.StatusOK { 37 | panic("status code is not 200") 38 | } 39 | 40 | data, err := io.ReadAll(resp.Body) 41 | println(string(data)) 42 | } 43 | -------------------------------------------------------------------------------- /pkg/generator/testdata/expected_javascript_code.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | 14 | async function makeRequest() { 15 | const headers = new Headers(); 16 | headers.append("User-Agent", "atest"); 17 | 18 | const requestOptions = { 19 | method: "GET", 20 | headers: headers, 21 | redirect: "follow" 22 | }; 23 | 24 | try { 25 | const response = await fetch("https://www.baidu.com", requestOptions); 26 | if (response.ok) { // Check if HTTP status code is 200/OK 27 | const text = await response.text(); 28 | console.log(text); 29 | } else { 30 | throw new Error('Network response was not ok. Status code: ' + response.status); 31 | } 32 | } catch (error) { 33 | console.error('Fetch error:', error); 34 | } 35 | } 36 | 37 | makeRequest(); 38 | -------------------------------------------------------------------------------- /pkg/generator/testdata/expected_python_code.txt: -------------------------------------------------------------------------------- 1 | ''' 2 | Copyright 2024-2025 API Testing Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | ''' 13 | import io 14 | import requests 15 | from urllib.parse import urlencode 16 | 17 | def main(): 18 | body = io.BytesIO(b"""""") 19 | headers = {"User-Agent": "atest"} 20 | try: 21 | req = requests.Request("GET", "https://www.baidu.com", headers=headers, data=body) 22 | except requests.RequestException as e: 23 | raise e 24 | 25 | resp = requests.Session().send(req.prepare(), verify=False) 26 | if resp.status_code != 200: 27 | raise Exception("status code is not 200") 28 | 29 | data = resp.content 30 | print(data.decode("utf-8")) 31 | 32 | if __name__ == "__main__": 33 | main() 34 | -------------------------------------------------------------------------------- /pkg/generator/testdata/expected_python_cookie_request_code.txt: -------------------------------------------------------------------------------- 1 | ''' 2 | Copyright 2024-2025 API Testing Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | ''' 13 | import io 14 | import requests 15 | from urllib.parse import urlencode 16 | 17 | def main(): 18 | data = {} 19 | data["key"] = "value" 20 | encoded_data = urlencode(data) 21 | body = io.BytesIO(encoded_data.encode("utf-8")) 22 | headers = {"User-Agent": "atest"} 23 | cookies = {"name": "value"} 24 | try: 25 | req = requests.Request("GET", "https://www.baidu.com", headers=headers, cookies=cookies, data=body) 26 | except requests.RequestException as e: 27 | raise e 28 | 29 | resp = requests.Session().send(req.prepare(), verify=False) 30 | if resp.status_code != 200: 31 | raise Exception("status code is not 200") 32 | 33 | data = resp.content 34 | print(data.decode("utf-8")) 35 | 36 | if __name__ == "__main__": 37 | main() 38 | -------------------------------------------------------------------------------- /pkg/generator/testdata/expected_python_form_request_code.txt: -------------------------------------------------------------------------------- 1 | ''' 2 | Copyright 2024-2025 API Testing Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | ''' 13 | import io 14 | import requests 15 | from urllib.parse import urlencode 16 | 17 | def main(): 18 | data = {} 19 | data["key"] = "value" 20 | encoded_data = urlencode(data) 21 | body = io.BytesIO(encoded_data.encode("utf-8")) 22 | headers = {"User-Agent": "atest"} 23 | try: 24 | req = requests.Request("GET", "https://www.baidu.com", headers=headers, data=body) 25 | except requests.RequestException as e: 26 | raise e 27 | 28 | resp = requests.Session().send(req.prepare(), verify=False) 29 | if resp.status_code != 200: 30 | raise Exception("status code is not 200") 31 | 32 | data = resp.content 33 | print(data.decode("utf-8")) 34 | 35 | if __name__ == "__main__": 36 | main() 37 | -------------------------------------------------------------------------------- /pkg/generator/testdata/expected_suite_from_postman.yaml: -------------------------------------------------------------------------------- 1 | name: New Collection 2 | items: 3 | - name: New Request 4 | request: 5 | api: http://localhost?key=value 6 | method: GET 7 | header: 8 | key: value 9 | body: '{}' -------------------------------------------------------------------------------- /pkg/generator/testdata/expected_suite_from_sub_postman.yaml: -------------------------------------------------------------------------------- 1 | name: Sub 2 | items: 3 | - name: Get Sub Get New Request 4 | request: 5 | api: http://localhost?key=value 6 | method: GET 7 | header: 8 | key: value 9 | body: '{}' -------------------------------------------------------------------------------- /pkg/generator/testdata/expected_testsuite.yaml: -------------------------------------------------------------------------------- 1 | name: API Testing 2 | api: http://localhost:8080/server.Runner 3 | items: 4 | - name: hello-jmeter 5 | request: 6 | api: /GetSuites 7 | method: POST 8 | body: sample 9 | -------------------------------------------------------------------------------- /pkg/generator/testdata/native.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": "IyFhcGktdGVzdGluZwojIHlhbWwtbGFuZ3VhZ2Utc2VydmVyOiAkc2NoZW1hPWh0dHBzOi8vbGludXhzdXJlbi5naXRodWIuaW8vYXBpLXRlc3RpbmcvYXBpLXRlc3Rpbmctc2NoZW1hLmpzb24KbmFtZTogYmFkCmFwaTogYmFkCml0ZW1zOgogICAgLSBuYW1lOiBvbmUKICAgICAgcmVxdWVzdDoKICAgICAgICBhcGk6IC9vbmUKICAgICAgICBtZXRob2Q6IEdFVAogICAgLSBuYW1lOiB0d28KICAgICAgcmVxdWVzdDoKICAgICAgICBhcGk6IC90d28KICAgICAgICBtZXRob2Q6IFBPU1QKICAgICAgICBxdWVyeToKICAgICAgICAgICAgYmJiOiBiYmIKICAgICAgICBoZWFkZXI6CiAgICAgICAgICAgIGFhYTogYWFhCiAgICAgIGV4cGVjdDoKICAgICAgICBzdGF0dXNDb2RlOiAyMDAK" 3 | } -------------------------------------------------------------------------------- /pkg/generator/testdata/postman-sub.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "84b8940a-009e-4127-b84e-f4d6fd6b9972", 4 | "name": "Sub", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 6 | "_exporter_id": "19536120" 7 | }, 8 | "item": [ 9 | { 10 | "name": "Get", 11 | "item": [ 12 | { 13 | "name": "Sub Get", 14 | "item": [ 15 | { 16 | "name": "New Request", 17 | "request": { 18 | "method": "GET", 19 | "header": [ 20 | { 21 | "key": "key", 22 | "value": "value", 23 | "description": "description", 24 | "type": "text" 25 | } 26 | ], 27 | "body": { 28 | "mode": "raw", 29 | "raw": "{}" 30 | }, 31 | "url": { 32 | "raw": "http://localhost?key=value" 33 | } 34 | } 35 | } 36 | ] 37 | } 38 | ] 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /pkg/generator/testdata/postman.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "0da1f6bf-fdbb-46a5-ac46-873564e2259c", 4 | "name": "New Collection", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 6 | "_exporter_id": "6795120", 7 | "_collection_link": "https://www.postman.com/ks-devops/workspace/kubesphere-devops/collection/6795120-0da1f6bf-fdbb-46a5-ac46-873564e2259c?action=share&creator=6795120&source=collection_link" 8 | }, 9 | "item": [ 10 | { 11 | "name": "New Request", 12 | "protocolProfileBehavior": { 13 | "disableBodyPruning": true 14 | }, 15 | "request": { 16 | "method": "GET", 17 | "header": [ 18 | { 19 | "key": "key", 20 | "value": "value", 21 | "description": "description", 22 | "type": "text" 23 | } 24 | ], 25 | "body": { 26 | "mode": "raw", 27 | "raw": "{}" 28 | }, 29 | "url": { 30 | "raw": "http://localhost?key=value" 31 | } 32 | } 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /pkg/generator/testdata/simple.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Library RequestsLibrary 3 | 4 | *** Test Cases *** 5 | simple 6 | ${response}= GET http://foo 7 | -------------------------------------------------------------------------------- /pkg/generator/testdata/suite.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Library RequestsLibrary 3 | 4 | *** Test Cases *** 5 | one 6 | ${headers}= Create Dictionary key1 value1 7 | ${response}= GET http://foo headers=${headers} 8 | two 9 | ${headers}= Create Dictionary key2 value2 10 | ${response}= GET http://foo headers=${headers} 11 | -------------------------------------------------------------------------------- /pkg/generator/testdata/with-headers.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Library RequestsLibrary 3 | 4 | *** Test Cases *** 5 | simple 6 | ${headers}= Create Dictionary key value 7 | ${response}= GET http://foo headers=${headers} 8 | -------------------------------------------------------------------------------- /pkg/limit/limiter_long_test.go: -------------------------------------------------------------------------------- 1 | //go:build longtest 2 | // +build longtest 3 | 4 | /* 5 | Copyright 2023 API Testing Authors. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package limit_test 21 | 22 | import ( 23 | "testing" 24 | "time" 25 | 26 | "github.com/linuxsuren/api-testing/pkg/limit" 27 | "github.com/stretchr/testify/assert" 28 | ) 29 | 30 | func TestLimiterWithLongTime(t *testing.T) { 31 | for i := 0; i < 10; i++ { 32 | testLimiter(t, int32(8+i*2)) 33 | } 34 | } 35 | 36 | func testLimiter(t *testing.T, count int32) { 37 | t.Log("test limit with count", count) 38 | limiter := limit.NewDefaultRateLimiter(count, 1) 39 | num := int32(0) 40 | 41 | loop := true 42 | go func(l limit.RateLimiter) { 43 | for loop { 44 | l.Accept() 45 | num += 1 46 | } 47 | }(limiter) 48 | 49 | select { 50 | case <-time.After(time.Second): 51 | loop = false 52 | } 53 | assert.True(t, num <= count+1, num) 54 | } 55 | -------------------------------------------------------------------------------- /pkg/limit/limiter_test.go: -------------------------------------------------------------------------------- 1 | package limit 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestLimiter(t *testing.T) { 11 | t.Log("run rate limit test") 12 | limiter := NewDefaultRateLimiter(0, 0) 13 | num := 0 14 | 15 | loop := true 16 | go func(l RateLimiter) { 17 | for loop { 18 | l.Accept() 19 | num += 1 20 | } 21 | }(limiter) 22 | 23 | select { 24 | case <-time.After(time.Second): 25 | loop = false 26 | limiter.Stop() 27 | } 28 | assert.True(t, num <= 10, num) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/mock/server.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package mock 17 | 18 | import ( 19 | "net/http" 20 | ) 21 | 22 | type Loadable interface { 23 | Load() error 24 | } 25 | 26 | type DynamicServer interface { 27 | Start(reader Reader, prefix string) error 28 | SetupHandler(reader Reader, prefix string) (http.Handler, error) 29 | Stop() error 30 | GetPort() string 31 | EnableMetrics() 32 | Loadable 33 | } 34 | 35 | const ( 36 | headerMockServer = "Mock-Server" 37 | ) 38 | -------------------------------------------------------------------------------- /pkg/render/data/templateUsage.yaml: -------------------------------------------------------------------------------- 1 | randImage: | 2 | {{ randImage 100 100 }} 3 | randAscii: | 4 | {{ randAscii 5 }} 5 | randPdf: | 6 | {{ randPdf "content" }} 7 | randZip: | 8 | {{ randZip 5 }} 9 | -------------------------------------------------------------------------------- /pkg/render/doc.go: -------------------------------------------------------------------------------- 1 | // Package render provides a simple way to render as template 2 | package render 3 | -------------------------------------------------------------------------------- /pkg/render/image_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language 24 permissions and 14 | limitations under the License. 15 | */ 16 | package render 17 | 18 | import ( 19 | "encoding/base64" 20 | "strings" 21 | "testing" 22 | 23 | "github.com/linuxsuren/api-testing/pkg/util" 24 | "github.com/stretchr/testify/assert" 25 | ) 26 | 27 | func TestRandImage(t *testing.T) { 28 | tests := []struct { 29 | width, height int 30 | }{{ 31 | width: 0, 32 | height: 10, 33 | }, { 34 | width: 10, 35 | height: -1, 36 | }, { 37 | width: 10240, 38 | height: 10240, 39 | }} 40 | for _, tt := range tests { 41 | data, err := generateRandomImage(tt.width, tt.height) 42 | assert.NoError(t, err, err) 43 | 44 | imageStr := strings.TrimPrefix(string(data), util.ImageBase64Prefix) 45 | _, err = base64.StdEncoding.DecodeString(imageStr) 46 | assert.NoError(t, err, err) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /pkg/render/local.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language 24 permissions and 14 | limitations under the License. 15 | */ 16 | package render 17 | 18 | import ( 19 | "encoding/base64" 20 | "fmt" 21 | "os" 22 | 23 | "github.com/linuxsuren/api-testing/pkg/util" 24 | ) 25 | 26 | func readFile(filename string) (data string, err error) { 27 | var rawData []byte 28 | if rawData, err = os.ReadFile(filename); err == nil { 29 | data = fmt.Sprintf("%s%s", util.BinaryBase64Prefix, base64.StdEncoding.EncodeToString(rawData)) 30 | } 31 | return 32 | } 33 | -------------------------------------------------------------------------------- /pkg/render/local_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language 24 permissions and 14 | limitations under the License. 15 | */ 16 | package render 17 | 18 | import ( 19 | "testing" 20 | 21 | "github.com/stretchr/testify/assert" 22 | ) 23 | 24 | func TestReadFile(t *testing.T) { 25 | data, err := readFile("data/templateUsage.yaml") 26 | assert.Nil(t, err) 27 | assert.Equal(t, "data:application/octet-stream;base64,cmFuZEltYWdlOiB8CiAge3sgcmFuZEltYWdlIDEwMCAxMDAgfX0KcmFuZEFzY2lpOiB8CiAge3sgcmFuZEFzY2lpIDUgfX0KcmFuZFBkZjogfAogIHt7IHJhbmRQZGYgImNvbnRlbnQiIH19CnJhbmRaaXA6IHwKICB7eyByYW5kWmlwIDUgfX0K", data) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/render/pdf_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language 24 permissions and 14 | limitations under the License. 15 | */ 16 | package render 17 | 18 | import ( 19 | "testing" 20 | 21 | "github.com/stretchr/testify/assert" 22 | ) 23 | 24 | func TestRandPdf(t *testing.T) { 25 | data, err := generateRandomPdf("hello") 26 | assert.NotEmpty(t, data) 27 | assert.NoError(t, err, err) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/render/secret.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package render 17 | 18 | import ( 19 | "github.com/linuxsuren/api-testing/pkg/secret" 20 | ) 21 | 22 | type nonSecretGetter struct { 23 | value string 24 | err error 25 | } 26 | 27 | func (n *nonSecretGetter) GetSecret(name string) (s secret.Secret, err error) { 28 | s.Value = n.value 29 | s.Name = name 30 | err = n.err 31 | return 32 | } 33 | -------------------------------------------------------------------------------- /pkg/render/zip.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language 24 permissions and 14 | limitations under the License. 15 | */ 16 | package render 17 | 18 | import ( 19 | "archive/zip" 20 | "bytes" 21 | "encoding/base64" 22 | "fmt" 23 | "io" 24 | 25 | "github.com/linuxsuren/api-testing/pkg/util" 26 | ) 27 | 28 | func generateRandomZip(count int) (data string, err error) { 29 | var buf bytes.Buffer 30 | w := zip.NewWriter(&buf) 31 | 32 | if count < 1 { 33 | count = 1 34 | } 35 | if count > 100 { 36 | count = 100 37 | } 38 | 39 | for i := 0; i < count; i++ { 40 | name := fmt.Sprintf("%d.txt", i) 41 | var f io.Writer 42 | f, err = w.Create(name) 43 | if err == nil { 44 | _, err = f.Write([]byte(name)) 45 | } 46 | 47 | if err != nil { 48 | return 49 | } 50 | } 51 | 52 | if err = w.Close(); err == nil { 53 | data = fmt.Sprintf("%s%s", util.ZIPBase64Prefix, base64.StdEncoding.EncodeToString(buf.Bytes())) 54 | } 55 | return 56 | } 57 | -------------------------------------------------------------------------------- /pkg/render/zip_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language 24 permissions and 14 | limitations under the License. 15 | */ 16 | package render 17 | 18 | import ( 19 | "testing" 20 | 21 | "github.com/stretchr/testify/assert" 22 | ) 23 | 24 | func TestRandZip(t *testing.T) { 25 | for i := 0; i < 110; i++ { 26 | data, err := generateRandomZip(i) 27 | assert.NotEmpty(t, data) 28 | assert.NoError(t, err, err) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /pkg/runner/doc.go: -------------------------------------------------------------------------------- 1 | // Package runner responsible for excute the test case 2 | package runner 3 | -------------------------------------------------------------------------------- /pkg/runner/grpc_test/test.pb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/pkg/runner/grpc_test/test.pb -------------------------------------------------------------------------------- /pkg/runner/grpc_test/testassets/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIAVkpfC5iACaZYvvaf1NevIosGhBKwLS5ZwwnBkokjEhoAoGCCqGSM49 3 | AwEHoUQDQgAE8/i0CVHM+az+k7rS0WkxlkoSWOm9T5f8J1q3KnIGu00rOXRRviiy 4 | bw3czSo8eruRtFv28A0VFZdEnYraHK/2tg== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /pkg/runner/http_reverse_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package runner 18 | 19 | import ( 20 | "testing" 21 | 22 | atest "github.com/linuxsuren/api-testing/pkg/testing" 23 | "github.com/linuxsuren/api-testing/pkg/util" 24 | "github.com/stretchr/testify/assert" 25 | ) 26 | 27 | func TestAuthHeaderMutator(t *testing.T) { 28 | mutator := &authHeaderMissingMutator{} 29 | testcase := &atest.TestCase{ 30 | Request: atest.Request{ 31 | Header: map[string]string{ 32 | util.Authorization: "Basic xxyy", 33 | }, 34 | }, 35 | } 36 | result := mutator.Render(testcase) 37 | _, ok := result.Request.Header[util.Authorization] 38 | assert.False(t, ok) 39 | assert.NotEmpty(t, testcase.Request.Header[util.Authorization]) 40 | } 41 | -------------------------------------------------------------------------------- /pkg/runner/kubernetes/doc.go: -------------------------------------------------------------------------------- 1 | // Package kubernetes provides a low level client for small footprint consideration 2 | package kubernetes 3 | -------------------------------------------------------------------------------- /pkg/runner/kubernetes/verify.go: -------------------------------------------------------------------------------- 1 | package kubernetes 2 | 3 | import "github.com/expr-lang/expr" 4 | 5 | // PodValidatorFunc returns a expr for checking pod existing 6 | func PodValidatorFunc() expr.Option { 7 | return expr.Function("pod", podValidator, new(func(...string) ResourceValidator)) 8 | } 9 | 10 | // KubernetesValidatorFunc returns a expr for checking the generic Kubernetes resources 11 | func KubernetesValidatorFunc() expr.Option { 12 | return expr.Function("k8s", resourceValidator, new(func(interface{}, ...string) ResourceValidator)) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/runner/monitor/dumy_monitor.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package monitor 18 | 19 | import ( 20 | context "context" 21 | 22 | grpc "google.golang.org/grpc" 23 | ) 24 | 25 | type dumyMonitor struct{} 26 | 27 | func NewDumyMonitor() MonitorClient { 28 | return &dumyMonitor{} 29 | } 30 | 31 | func (m *dumyMonitor) GetResourceUsage(ctx context.Context, in *Target, opts ...grpc.CallOption) (*ResourceUsage, error) { 32 | return &ResourceUsage{}, nil 33 | } 34 | -------------------------------------------------------------------------------- /pkg/runner/monitor/monitor.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/linuxsuren/api-testing/pkg/runner/monitor"; 4 | 5 | package monitor; 6 | 7 | service Monitor { 8 | rpc GetResourceUsage(Target) returns (ResourceUsage) {} 9 | } 10 | 11 | message ResourceUsage { 12 | uint64 memory = 1; 13 | uint64 cpu = 2; 14 | } 15 | 16 | message Target { 17 | string name = 1; 18 | } 19 | -------------------------------------------------------------------------------- /pkg/runner/reporter_discard.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package runner 18 | 19 | type discardTestReporter struct { 20 | } 21 | 22 | // NewDiscardTestReporter creates a test reporter which discard everything 23 | func NewDiscardTestReporter() TestReporter { 24 | return &discardTestReporter{} 25 | } 26 | 27 | // PutRecord does nothing 28 | func (r *discardTestReporter) PutRecord(*ReportRecord) { 29 | // Do nothing which is the design purpose 30 | } 31 | 32 | // GetAllRecords does nothing 33 | func (r *discardTestReporter) GetAllRecords() []*ReportRecord { 34 | return nil 35 | } 36 | 37 | // ExportAllReportResults does nothing 38 | func (r *discardTestReporter) ExportAllReportResults() (ReportResultSlice, error) { 39 | return nil, nil 40 | } 41 | 42 | func (r *discardTestReporter) GetResourceUsage() []ResourceUsage { 43 | return nil 44 | } 45 | -------------------------------------------------------------------------------- /pkg/runner/reporter_discard_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package runner_test 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/linuxsuren/api-testing/pkg/runner" 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | func TestDiscardTestReporter(t *testing.T) { 27 | reporter := runner.NewDiscardTestReporter() 28 | assert.NotNil(t, reporter) 29 | assert.Nil(t, reporter.GetAllRecords()) 30 | 31 | result, err := reporter.ExportAllReportResults() 32 | assert.Nil(t, result) 33 | assert.Nil(t, err) 34 | 35 | reporter.PutRecord(&runner.ReportRecord{}) 36 | } 37 | -------------------------------------------------------------------------------- /pkg/runner/testdata/generic_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "linuxsuren", 3 | "number": 1 4 | } 5 | -------------------------------------------------------------------------------- /pkg/runner/testdata/json-result.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Name": "foo", 4 | "API": "api", 5 | "Count": 3, 6 | "Average": 3, 7 | "Max": 4, 8 | "Min": 2, 9 | "QPS": 0, 10 | "Error": 0, 11 | "LastErrorMessage": "" 12 | }, 13 | { 14 | "Name": "bar", 15 | "API": "api", 16 | "Count": 3, 17 | "Average": 3, 18 | "Max": 4, 19 | "Min": 2, 20 | "QPS": 0, 21 | "Error": 0, 22 | "LastErrorMessage": "" 23 | } 24 | ] -------------------------------------------------------------------------------- /pkg/runner/writer.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package runner 18 | 19 | import ( 20 | "io" 21 | 22 | "github.com/linuxsuren/api-testing/pkg/apispec" 23 | ) 24 | 25 | // ReportResultWriter is the interface of the report writer 26 | type ReportResultWriter interface { 27 | Output([]ReportResult) error 28 | WithAPICoverage(apiCoverage apispec.APICoverage) ReportResultWriter 29 | WithResourceUsage([]ResourceUsage) ReportResultWriter 30 | GetWriter() io.Writer 31 | } 32 | -------------------------------------------------------------------------------- /pkg/runner/writer_templates/example.tpl: -------------------------------------------------------------------------------- 1 | [ 2 | {{range $index, $result := .}} 3 | { 4 | "Name": "{{$result.Name}}", 5 | "API": "{{$result.API}}", 6 | "Count": {{$result.Count}}, 7 | "Average": "{{$result.Average}}", 8 | "Max": "{{$result.Max}}", 9 | "Min": "{{$result.Min}}", 10 | "QPS": {{$result.QPS}}, 11 | "Error": {{$result.Error}}, 12 | "LastErrorMessage": "{{$result.LastErrorMessage}}" 13 | } 14 | {{end}} 15 | ] 16 | -------------------------------------------------------------------------------- /pkg/runner/writer_templates/server.go: -------------------------------------------------------------------------------- 1 | package writer_templates 2 | 3 | import ( 4 | "context" 5 | "log" 6 | ) 7 | 8 | type ReportServer struct { 9 | UnimplementedReportWriterServer 10 | } 11 | 12 | func (s *ReportServer) SendReportResult(ctx context.Context, req *ReportResultRepeated) (*Empty, error) { 13 | // print received data 14 | for _, result := range req.Data { 15 | log.Printf("Received report: %+v", result) 16 | } 17 | return &Empty{}, nil 18 | } 19 | -------------------------------------------------------------------------------- /pkg/runner/writer_templates/writer.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/linuxsuren/api-testing/pkg/runner/writer_templates"; 4 | 5 | package writer_templates; 6 | 7 | service ReportWriter{ 8 | rpc SendReportResult(ReportResultRepeated)returns(Empty); 9 | } 10 | 11 | message ReportResultRepeated{ 12 | repeated ReportResult data= 1; 13 | } 14 | 15 | message ReportResult { 16 | string Name = 1; 17 | string API = 2; 18 | int32 Count = 3; 19 | int64 Average = 4; 20 | int64 Max = 5; 21 | int64 Min = 6; 22 | int32 QPS = 7; 23 | int32 Error = 8; 24 | string LastErrorMessage = 9; 25 | } 26 | 27 | message Empty { 28 | } -------------------------------------------------------------------------------- /pkg/secret/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package secret 18 | 19 | type Secret struct { 20 | Name string 21 | Value string 22 | } 23 | 24 | type SecretGetter interface { 25 | GetSecret(name string) (secret Secret, err error) 26 | } 27 | -------------------------------------------------------------------------------- /pkg/server/constant.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package server 18 | 19 | import _ "embed" 20 | 21 | const ( 22 | HeaderKeyStoreName = "X-Store-Name" 23 | ) 24 | 25 | //go:embed server.swagger.json 26 | var SwaggerJSON []byte 27 | -------------------------------------------------------------------------------- /pkg/server/data/headers.yaml: -------------------------------------------------------------------------------- 1 | - key: User-Agent 2 | value: "" 3 | - key: Content-Type 4 | value: application/json 5 | - key: Content-Type 6 | value: application/json-patch+json 7 | - key: Content-Type 8 | value: application/merge-patch+json 9 | - key: Content-Type 10 | value: application/apply-patch+yaml 11 | - key: Content-Type 12 | value: application/x-www-form-urlencoded 13 | - key: Content-Type 14 | value: multipart/form-data 15 | - key: Accept-Language 16 | value: en-US,en;q=0.5 17 | - key: Authorization 18 | value: "Bearer token" 19 | - key: Authorization 20 | value: Basic {{ base64 "admin:123456" }} 21 | -------------------------------------------------------------------------------- /pkg/server/fake.yaml: -------------------------------------------------------------------------------- 1 | #!api-testing 2 | # yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-schema.json 3 | name: fake 4 | -------------------------------------------------------------------------------- /pkg/server/gateway.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package server 17 | 18 | import ( 19 | "context" 20 | "net/http" 21 | 22 | "google.golang.org/grpc/metadata" 23 | ) 24 | 25 | // MetadataStoreFunc is a function that extracts metadata from a request. 26 | func MetadataStoreFunc(ctx context.Context, r *http.Request) (md metadata.MD) { 27 | store := r.Header.Get(HeaderKeyStoreName) 28 | md = metadata.Pairs(HeaderKeyStoreName, store) 29 | 30 | if auth := r.Header.Get("X-Auth"); auth != "" { 31 | md.Set("Auth", auth) 32 | } 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /pkg/server/gateway_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package server 17 | 18 | import ( 19 | "context" 20 | "net/http" 21 | "testing" 22 | 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | func TestMetadataStoreFunc(t *testing.T) { 27 | req, err := http.NewRequest(http.MethodGet, "/", nil) 28 | req.Header.Set(HeaderKeyStoreName, "test") 29 | if !assert.NoError(t, err) { 30 | return 31 | } 32 | 33 | md := MetadataStoreFunc(context.TODO(), req) 34 | assert.Equal(t, "test", md.Get(HeaderKeyStoreName)[0]) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/server/proto.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package server 17 | 18 | import _ "embed" 19 | 20 | // GetProtos returns the proto files. 21 | // Key is filename, value is the content. 22 | func GetProtos() map[string]string { 23 | return map[string]string{ 24 | "server.proto": protoServer, 25 | } 26 | } 27 | 28 | //go:embed server.proto 29 | var protoServer string 30 | -------------------------------------------------------------------------------- /pkg/server/proto_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package server_test 17 | 18 | import ( 19 | "testing" 20 | 21 | "github.com/linuxsuren/api-testing/pkg/server" 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestGetProtos(t *testing.T) { 26 | protos := server.GetProtos() 27 | assert.Equal(t, 1, len(protos)) 28 | 29 | exists := []string{"server.proto"} 30 | for _, key := range exists { 31 | content, ok := protos[key] 32 | assert.True(t, ok) 33 | assert.NotEmpty(t, content) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /pkg/server/testdata/postman.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "0da1f6bf-fdbb-46a5-ac46-873564e2259c", 4 | "name": "NewCollection", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 6 | "_exporter_id": "6795120", 7 | "_collection_link": "https://www.postman.com/ks-devops/workspace/kubesphere-devops/collection/6795120-0da1f6bf-fdbb-46a5-ac46-873564e2259c?action=share&creator=6795120&source=collection_link" 8 | }, 9 | "item": [ 10 | { 11 | "name": "New Request", 12 | "protocolProfileBehavior": { 13 | "disableBodyPruning": true 14 | }, 15 | "request": { 16 | "method": "GET", 17 | "header": [ 18 | { 19 | "key": "key", 20 | "value": "value", 21 | "description": "description", 22 | "type": "text" 23 | } 24 | ], 25 | "body": { 26 | "mode": "raw", 27 | "raw": "{}" 28 | }, 29 | "url": { 30 | "raw": "http://localhost?key=value" 31 | } 32 | } 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /pkg/server/testdata/simple.yaml: -------------------------------------------------------------------------------- 1 | name: simple 2 | api: http://foo 3 | items: 4 | - name: get 5 | request: 6 | api: http://foo 7 | header: 8 | key: value 9 | - name: query 10 | request: 11 | api: / -------------------------------------------------------------------------------- /pkg/server/testdata/simple_testcase.yaml: -------------------------------------------------------------------------------- 1 | name: get 2 | request: 3 | api: http://bar -------------------------------------------------------------------------------- /pkg/server/testdata/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "sample", 5 | "title": "sample", 6 | "version": "1.0.0" 7 | }, 8 | "paths": { 9 | "/api/v1/users": { 10 | "get": { 11 | "summary": "summary", 12 | "operationId": "getUsers" 13 | }, 14 | "post": { 15 | "summary": "summary", 16 | "operationId": "createUser" 17 | } 18 | }, 19 | "/api/v1/users/{user}": { 20 | "get": { 21 | "summary": "summary", 22 | "operationId": "getUser" 23 | }, 24 | "delete": { 25 | "summary": "summary", 26 | "operationId": "deleteUser" 27 | }, 28 | "put": { 29 | "summary": "summary", 30 | "operationId": "updateUser" 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /pkg/service/runner.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package service 17 | 18 | import ( 19 | "fmt" 20 | "net/http" 21 | ) 22 | 23 | // WebRunnerHandler accepts the HTTP requests and run the testSuite 24 | func WebRunnerHandler(w http.ResponseWriter, r *http.Request, 25 | params map[string]string) { 26 | testSuite := params["suite"] 27 | testCase := params["case"] 28 | 29 | fmt.Println(testSuite, testCase) 30 | fmt.Println(r.URL.Query()) 31 | } 32 | -------------------------------------------------------------------------------- /pkg/service/sbom.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package service 18 | 19 | import ( 20 | "net/http" 21 | 22 | ui "github.com/linuxsuren/api-testing/console/atest-ui" 23 | "github.com/linuxsuren/api-testing/pkg/util" 24 | "github.com/linuxsuren/api-testing/pkg/version" 25 | ) 26 | 27 | func SBomHandler(w http.ResponseWriter, r *http.Request, 28 | params map[string]string) { 29 | modMap, err := version.GetModVersions("") 30 | packageJSON := ui.GetPackageJSON() 31 | if err != nil { 32 | w.WriteHeader(http.StatusInternalServerError) 33 | w.Write([]byte(err.Error())) 34 | } else { 35 | data := make(map[string]interface{}) 36 | data["js"] = packageJSON 37 | data["go"] = modMap 38 | util.WriteAsJSON(data, w) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /pkg/testing/doc.go: -------------------------------------------------------------------------------- 1 | // Package testing provide the test case functions 2 | package testing 3 | -------------------------------------------------------------------------------- /pkg/testing/testdata/duplicated-names.yaml: -------------------------------------------------------------------------------- 1 | name: duplicated names 2 | items: 3 | - name: projects 4 | request: 5 | api: https://foo 6 | - name: projects 7 | request: 8 | api: https://foo -------------------------------------------------------------------------------- /pkg/testing/testdata/generic_body.json: -------------------------------------------------------------------------------- 1 | {"name": "{{.Name}}"} 2 | -------------------------------------------------------------------------------- /pkg/testing/testdata/invalid-testcase.yaml: -------------------------------------------------------------------------------- 1 | name: projects 2 | request: 3 | api: https://foo 4 | expect: 5 | statuscode: 200 -------------------------------------------------------------------------------- /pkg/testing/testdata/stores.yaml: -------------------------------------------------------------------------------- 1 | stores: 2 | - name: db 3 | owner: "" 4 | kind: 5 | name: database 6 | url: localhost:7071 7 | enabled: true 8 | description: "" 9 | url: localhost:4000 10 | username: root 11 | password: "" 12 | readonly: false 13 | disabled: false 14 | properties: 15 | database: test 16 | - name: git 17 | owner: rick 18 | kind: 19 | name: "" 20 | url: "" 21 | enabled: false 22 | description: "" 23 | url: "" 24 | username: "" 25 | password: "" 26 | readonly: false 27 | disabled: false 28 | properties: {} 29 | plugins: 30 | - name: database 31 | url: localhost:7071 32 | enabled: true 33 | -------------------------------------------------------------------------------- /pkg/testing/testdata/testcase.yaml: -------------------------------------------------------------------------------- 1 | name: projects 2 | request: 3 | api: https://foo 4 | expect: 5 | statusCode: 200 -------------------------------------------------------------------------------- /pkg/util/base64.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | const ( 20 | ImageBase64Prefix = "data:image/png;base64," 21 | PDFBase64Prefix = "data:application/pdf;base64," 22 | ZIPBase64Prefix = "data:application/zip;base64," 23 | BinaryBase64Prefix = "data:application/octet-stream;base64," 24 | ) 25 | -------------------------------------------------------------------------------- /pkg/util/error.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package util 17 | 18 | import ( 19 | "fmt" 20 | "net/http" 21 | ) 22 | 23 | // OKOrErrorMessage returns OK or error message 24 | func OKOrErrorMessage(err error) string { 25 | return OrErrorMessage(err, "OK") 26 | } 27 | 28 | // OrErrorMessage returns error message or message 29 | func OrErrorMessage(err error, message string) string { 30 | if err != nil { 31 | return err.Error() 32 | } 33 | return message 34 | } 35 | 36 | func ErrorWrap(err error, msg string, args ...interface{}) error { 37 | if err != nil { 38 | err = fmt.Errorf(msg, args...) 39 | } 40 | return err 41 | } 42 | 43 | // IgnoreErrServerClosed ignores ErrServerClosed 44 | func IgnoreErrServerClosed(err error) error { 45 | if err == http.ErrServerClosed { 46 | return nil 47 | } 48 | return err 49 | } 50 | -------------------------------------------------------------------------------- /pkg/util/error_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package util_test 17 | 18 | import ( 19 | "errors" 20 | "net/http" 21 | "testing" 22 | 23 | "github.com/linuxsuren/api-testing/pkg/util" 24 | "github.com/stretchr/testify/assert" 25 | ) 26 | 27 | func TestOkOrErrorMessage(t *testing.T) { 28 | assert.Equal(t, "OK", util.OKOrErrorMessage(nil)) 29 | assert.Equal(t, "test", util.OKOrErrorMessage(errors.New("test"))) 30 | } 31 | 32 | func TestIgnoreErrServerClosed(t *testing.T) { 33 | assert.Nil(t, util.IgnoreErrServerClosed(nil)) 34 | assert.Nil(t, util.IgnoreErrServerClosed(http.ErrServerClosed)) 35 | assert.Error(t, util.IgnoreErrServerClosed(errors.New("test"))) 36 | } 37 | -------------------------------------------------------------------------------- /pkg/util/expand.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package util 17 | 18 | import ( 19 | "regexp" 20 | "strings" 21 | ) 22 | 23 | // Expand the text with brace syntax. 24 | // Such as: /home/{good,bad} -> [/home/good, /home/bad] 25 | func Expand(text string) (result []string) { 26 | reg := regexp.MustCompile(`\{.*\}`) 27 | if reg.MatchString(text) { 28 | brace := reg.FindString(text) 29 | braceItem := strings.TrimPrefix(brace, "{") 30 | braceItem = strings.TrimSuffix(braceItem, "}") 31 | items := strings.Split(braceItem, ",") 32 | 33 | for _, item := range items { 34 | result = append(result, strings.ReplaceAll(text, brace, item)) 35 | } 36 | } else { 37 | result = []string{text} 38 | } 39 | return 40 | } 41 | -------------------------------------------------------------------------------- /pkg/util/expand_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package util_test 17 | 18 | import ( 19 | "testing" 20 | 21 | "github.com/linuxsuren/api-testing/pkg/util" 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestExpand(t *testing.T) { 26 | tests := []struct { 27 | name string 28 | input string 29 | expect []string 30 | }{{ 31 | name: "without brace", 32 | input: "/home", 33 | expect: []string{"/home"}, 34 | }, { 35 | name: "with brace", 36 | input: "/home/{good,bad}", 37 | expect: []string{"/home/good", "/home/bad"}, 38 | }, { 39 | name: "with brace, have suffix", 40 | input: "/home/{good,bad}.yaml", 41 | expect: []string{"/home/good.yaml", "/home/bad.yaml"}, 42 | }} 43 | for _, tt := range tests { 44 | t.Run(tt.name, func(t *testing.T) { 45 | got := util.Expand(tt.input) 46 | assert.Equal(t, tt.expect, got, got) 47 | }) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /pkg/util/home/common_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package home 18 | 19 | import ( 20 | "github.com/stretchr/testify/assert" 21 | "testing" 22 | ) 23 | 24 | func TestGetUserBinDir(t *testing.T) { 25 | assert.Contains(t, GetUserConfigDir(), "atest") 26 | assert.Contains(t, GetUserBinDir(), "bin") 27 | assert.Contains(t, GetUserDataDir(), "data") 28 | assert.Contains(t, GetExtensionSocketPath("fake"), "fake.sock") 29 | } 30 | -------------------------------------------------------------------------------- /pkg/util/home/darwin.go: -------------------------------------------------------------------------------- 1 | //go:build darwin 2 | 3 | /* 4 | Copyright 2024 API Testing Authors. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package home 20 | 21 | import ( 22 | "bytes" 23 | "os/exec" 24 | "strings" 25 | ) 26 | 27 | func Dir() string { 28 | // First prefer the HOME environmental variable 29 | if home := getCommonHomeDir(); home != "" { 30 | return home 31 | } 32 | 33 | var stdout bytes.Buffer 34 | cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`) 35 | cmd.Stdout = &stdout 36 | if err := cmd.Run(); err == nil { 37 | result := strings.TrimSpace(stdout.String()) 38 | if result != "" { 39 | return result 40 | } 41 | } 42 | 43 | return getHomeDirViaShell() 44 | } 45 | -------------------------------------------------------------------------------- /pkg/util/home/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package home provides a way to get the home directory of OS 18 | // Copied from https://github.com/mitchellh/go-homedir 19 | package home 20 | -------------------------------------------------------------------------------- /pkg/util/home/windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | /* 4 | Copyright 2024 API Testing Authors. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package home 20 | 21 | import ( 22 | "os" 23 | ) 24 | 25 | func Dir() string { 26 | // First prefer the HOME environmental variable 27 | if home := getCommonHomeDir(); home != "" { 28 | return home 29 | } 30 | 31 | // Prefer standard environment variable USERPROFILE 32 | if home := os.Getenv("USERPROFILE"); home != "" { 33 | return home 34 | } 35 | 36 | drive := os.Getenv("HOMEDRIVE") 37 | path := os.Getenv("HOMEPATH") 38 | home := drive + path 39 | if drive == "" || path == "" { 40 | return "" 41 | } 42 | 43 | return home 44 | } 45 | -------------------------------------------------------------------------------- /pkg/util/map.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package util 17 | 18 | // Keys returns a list of keys 19 | func Keys[T interface{}](data map[string]T) (keys []string) { 20 | keys = make([]string, len(data)) 21 | index := 0 22 | for k := range data { 23 | keys[index] = k 24 | index++ 25 | } 26 | return 27 | } 28 | -------------------------------------------------------------------------------- /pkg/util/map_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package util_test 17 | 18 | import ( 19 | "testing" 20 | 21 | "github.com/linuxsuren/api-testing/pkg/util" 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestKeys(t *testing.T) { 26 | t.Run("normal", func(t *testing.T) { 27 | assert.ElementsMatch(t, []string{"foo", "bar"}, 28 | util.Keys(map[string]interface{}{"foo": "xx", "bar": "xx"})) 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/util/net.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package util 17 | 18 | import ( 19 | "net" 20 | "strings" 21 | ) 22 | 23 | // GetPort returns the port of the listener 24 | func GetPort(listener net.Listener) string { 25 | if listener == nil { 26 | return "" 27 | } 28 | addr := listener.Addr().String() 29 | items := strings.Split(addr, ":") 30 | return items[len(items)-1] 31 | } 32 | -------------------------------------------------------------------------------- /pkg/util/path.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package util 17 | 18 | import "os" 19 | 20 | // PathExists checks if the target path exist or not 21 | func PathExists(path string) (ok bool, err error) { 22 | _, err = os.Stat(path) 23 | if err != nil && os.IsNotExist(err) { 24 | ok = false 25 | err = nil 26 | } else { 27 | ok = true 28 | } 29 | return 30 | } 31 | -------------------------------------------------------------------------------- /pkg/util/path_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package util_test 17 | 18 | import ( 19 | "os" 20 | "path" 21 | "testing" 22 | "time" 23 | 24 | "github.com/linuxsuren/api-testing/pkg/util" 25 | "github.com/stretchr/testify/assert" 26 | ) 27 | 28 | func TestPathExists(t *testing.T) { 29 | t.Run("exist", func(t *testing.T) { 30 | ok, err := util.PathExists(os.TempDir()) 31 | assert.True(t, ok) 32 | assert.NoError(t, err) 33 | }) 34 | 35 | t.Run("not exist", func(t *testing.T) { 36 | ok, err := util.PathExists(path.Join(os.TempDir(), time.Now().String())) 37 | assert.False(t, ok) 38 | assert.NoError(t, err) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /pkg/util/rand_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2015 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "strings" 21 | "testing" 22 | ) 23 | 24 | const ( 25 | maxRangeTestCount = 500 26 | testStringLength = 32 27 | ) 28 | 29 | func TestString(t *testing.T) { 30 | valid := "bcdfghjklmnpqrstvwxz2456789" 31 | for _, l := range []int{0, 1, 2, 10, 123} { 32 | s := String(l) 33 | if len(s) != l { 34 | t.Errorf("expected string of size %d, got %q", l, s) 35 | } 36 | for _, c := range s { 37 | if !strings.ContainsRune(valid, c) { 38 | t.Errorf("expected valid characters, got %v", c) 39 | } 40 | } 41 | } 42 | } 43 | 44 | func BenchmarkRandomStringGeneration(b *testing.B) { 45 | b.ResetTimer() 46 | var s string 47 | for i := 0; i < b.N; i++ { 48 | s = String(testStringLength) 49 | } 50 | b.StopTimer() 51 | if len(s) == 0 { 52 | b.Fatal(s) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /pkg/util/slice.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package util 17 | 18 | func RemoeEmptyFromSlice(items []string) []string { 19 | for i := 0; i < len(items); { 20 | if items[i] == "" { 21 | items = append(items[:i], items[i+1:]...) 22 | i++ 23 | } 24 | } 25 | return items 26 | } 27 | -------------------------------------------------------------------------------- /pkg/util/slice_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package util_test 17 | 18 | import ( 19 | "testing" 20 | 21 | "github.com/linuxsuren/api-testing/pkg/util" 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestRemoeEmptyFromSlice(t *testing.T) { 26 | assert.Equal(t, []string{"a", "b"}, util.RemoeEmptyFromSlice([]string{"", "a", "", "b"})) 27 | assert.Equal(t, []string{}, util.RemoeEmptyFromSlice([]string{""})) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/util/testdata/fuzz/FuzzEmptyThenDefault/a5d1a2517d90f203: -------------------------------------------------------------------------------- 1 | go test fuzz v1 2 | string("\u00a0") 3 | string("0") 4 | -------------------------------------------------------------------------------- /pkg/util/testdata/fuzz/FuzzZeroThenDefault/26953e5f8daf8575: -------------------------------------------------------------------------------- 1 | go test fuzz v1 2 | int(59) 3 | int(69) 4 | -------------------------------------------------------------------------------- /pkg/util/testdata/test.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinuxSuRen/api-testing/b572c780dd0d16bcdb78341cccf3dbe64d78e71b/pkg/util/testdata/test.zip -------------------------------------------------------------------------------- /pkg/version/constants.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Package version provides the version access of this app 17 | package version 18 | 19 | import "fmt" 20 | 21 | const UnknownVersion = "unknown" 22 | 23 | // should be injected during the build process 24 | var version string 25 | var date string 26 | var commit string 27 | 28 | // GetVersion returns the version 29 | func GetVersion() string { 30 | if version == "" { 31 | return UnknownVersion 32 | } 33 | return version 34 | } 35 | 36 | func GetDate() string { 37 | return date 38 | } 39 | 40 | func GetCommit() string { 41 | return commit 42 | } 43 | 44 | func GetDetailedVersion() string { 45 | return fmt.Sprintf(`Version: %s 46 | Date: %s`, version, date) 47 | } 48 | -------------------------------------------------------------------------------- /pkg/version/constants_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 API Testing Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package version_test 17 | 18 | import ( 19 | "testing" 20 | 21 | "github.com/linuxsuren/api-testing/pkg/version" 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestVersion(t *testing.T) { 26 | ver := version.GetVersion() 27 | assert.Equal(t, "unknown", ver) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/version/testdata/go.mod.txt: -------------------------------------------------------------------------------- 1 | module github.com/linuxsuren/api-testing 2 | 3 | go 1.22.4 4 | 5 | require ( 6 | github.com/a/b v0.0.1 7 | ) 8 | -------------------------------------------------------------------------------- /qodana.yaml: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------------------# 2 | # Qodana analysis is configured by qodana.yaml file # 3 | # https://www.jetbrains.com/help/qodana/qodana-yaml.html # 4 | #-------------------------------------------------------------------------------# 5 | version: "1.0" 6 | 7 | #Specify inspection profile for code analysis 8 | profile: 9 | name: qodana.starter 10 | 11 | #Enable inspections 12 | #include: 13 | # - name: 14 | 15 | #Disable inspections 16 | #exclude: 17 | # - name: 18 | # paths: 19 | # - 20 | 21 | #Execute shell command before Qodana execution (Applied in CI/CD pipeline) 22 | #bootstrap: sh ./prepare-qodana.sh 23 | 24 | #Install IDE plugins before Qodana execution (Applied in CI/CD pipeline) 25 | #plugins: 26 | # - id: #(plugin id can be found at https://plugins.jetbrains.com) 27 | 28 | #Specify Qodana linter for analysis (Applied in CI/CD pipeline) 29 | linter: jetbrains/qodana-go:latest 30 | -------------------------------------------------------------------------------- /sample/constants.go: -------------------------------------------------------------------------------- 1 | package sample 2 | 3 | import _ "embed" 4 | 5 | //go:embed testsuite-gitlab.yaml 6 | var TestSuiteGitLab string 7 | -------------------------------------------------------------------------------- /sample/grpc-sample.yaml: -------------------------------------------------------------------------------- 1 | #!api-testing 2 | # yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-schema.json 3 | # see also https://github.com/LinuxSuRen/api-testing 4 | name: grpc-sample 5 | api: 127.0.0.1:7070 6 | spec: 7 | grpc: 8 | import: 9 | - ./pkg/server 10 | protofile: server.proto 11 | serverReflection: true 12 | items: 13 | - name: GetVersion 14 | request: 15 | api: /server.Runner/GetVersion 16 | - name: FunctionsQuery 17 | request: 18 | api: /server.Runner/FunctionsQuery 19 | body: | 20 | { 21 | "name": "hello" 22 | } 23 | expect: 24 | body: | 25 | { 26 | "data": [ 27 | { 28 | "key": "hello", 29 | "value": "func() string" 30 | } 31 | ] 32 | } 33 | - name: FunctionsQueryStream 34 | request: 35 | api: /server.Runner/FunctionsQueryStream 36 | body: | 37 | [ 38 | { 39 | "name": "hello" 40 | }, 41 | { 42 | "name": "title" 43 | } 44 | ] 45 | expect: 46 | verify: 47 | - "len(data) == 2" 48 | -------------------------------------------------------------------------------- /sample/testsuite-gitee.yaml: -------------------------------------------------------------------------------- 1 | #!api-testing 2 | # yaml-language-server: $schema=/workspace/api-testing/docs/api-testing-schema.json 3 | name: Gitee 4 | api: https://gitee.com/api/v5 5 | param: 6 | repo: api-testing 7 | items: 8 | - name: stargazers 9 | before: 10 | items: 11 | - sleep(1) 12 | request: 13 | api: /repos/linuxsuren/{{.param.repo}}/stargazers 14 | expect: 15 | verify: 16 | - len(["data"]) > 0 17 | - name: branches 18 | request: 19 | api: /repos/linuxsuren/{{.param.repo}}/branches 20 | expect: 21 | verify: 22 | - len(filter(data, .name == "master")) == 1 23 | - name: branch 24 | request: 25 | api: /repos/linuxsuren/{{.param.repo}}/branches/{{(index .branches 0).name}} 26 | expect: 27 | verify: 28 | - len(data.name) > 0 29 | spec: 30 | kind: swagger 31 | url: https://gitee.com/api/v5/doc_json -------------------------------------------------------------------------------- /sample/testsuite-gitlab.yaml: -------------------------------------------------------------------------------- 1 | #!api-testing 2 | # yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-schema.json 3 | # https://docs.gitlab.com/ee/api/api_resources.html 4 | name: Gitlab 5 | api: https://gitlab.com/api/v4 6 | param: 7 | user: linuxsuren 8 | items: 9 | - name: projects 10 | request: 11 | api: /projects 12 | expect: 13 | statusCode: 200 14 | schema: | 15 | { 16 | "type": "array" 17 | } 18 | before: 19 | items: 20 | - "sleep(1)" 21 | after: 22 | items: 23 | - "sleep(1)" 24 | - name: project 25 | request: 26 | api: /projects/{{int64 (index .projects 0).id}} 27 | expect: 28 | statusCode: 200 29 | # bodyFieldsExpect: 30 | # http_url_to_repo: https://gitlab.com/senghuy/sr_chea_senghuy_spring_homework001.git 31 | verify: 32 | - data.http_url_to_repo startsWith "https" 33 | - data.http_url_to_repo endsWith ".git" 34 | - data.default_branch == 'master' or data.default_branch == 'main' 35 | - len(data.topics) >= 0 36 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.exclusions=extensions/store-etcd/remote/*.pb.go, pkg/server/*.pb.go, pkg/server/*.pb.gw.go, pkg/testing/remote/*.pb.go 2 | sonar.cpd.exclusions=extensions/store-etcd/remote/*.pb.go, pkg/server/*.pb.go, pkg/server/*.pb.gw.go, pkg/testing/remote/*.pb.go -------------------------------------------------------------------------------- /tools/SECURITY.md: -------------------------------------------------------------------------------- 1 | ## Reporting Security Issues 2 | 3 | The API Testing commnity takes a rigorous standpoint in annihilating the security issues in its software projects. API Testing is highly sensitive and forthcoming to issues pertaining to its features and functionality. 4 | 5 | ## REPORTING VULNERABILITY 6 | 7 | If you have apprehensions regarding API Testing's security or you discover vulnerability or potential threat, don’t hesitate to get in touch with the api-testing Security Team by dropping a mail at [api-testing-security@googlegroups.com](mailto:api-testing-security@googlegroups.com). In the mail, specify the description of the issue or potential threat. You are also urged to recommend the way to reproduce and replicate the issue. The API Testing community will get back to you after assessing and analysing the findings. 8 | 9 | PLEASE PAY ATTENTION to report the security issue on the security email before disclosing it on public domain. 10 | 11 | ## VULNERABILITY HANDLING 12 | 13 | An overview of the vulnerability handling process is: 14 | 15 | The reporter reports the vulnerability privately to API Testing community. 16 | The appropriate project's security team works privately with the reporter to resolve the vulnerability. 17 | A new release of the API Testing product concerned is made that includes the fix. 18 | The vulnerability is publically announced. 19 | -------------------------------------------------------------------------------- /tools/github-actions/setup-deps/action.yml: -------------------------------------------------------------------------------- 1 | name: setup-deps 2 | description: Install host system dependencies 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 8 | with: 9 | go-version: 1.23.x 10 | cache: true 11 | -------------------------------------------------------------------------------- /tools/make/desktop.mk: -------------------------------------------------------------------------------- 1 | # Building docs makefile defined. 2 | # 3 | # All make targets related to docs are defined in this file. 4 | 5 | ##@ Desktop 6 | 7 | .PHONY: desktop-start 8 | desktop-start: ## Start Electron Desktop 9 | desktop-start: 10 | cd console/atest-desktop && npm run start 11 | 12 | desktop-package: ## Package Electron Desktop 13 | desktop-package: build.embed.ui copy-to-desktop 14 | cd console/atest-desktop && npm i && npm run package 15 | 16 | desktop-make: build.embed.ui ## Make an Electron Desktop 17 | cd console/atest-desktop && npm i && npm run make 18 | 19 | desktop-publish: build.embed.ui ## Publish the Electron Desktop 20 | cd console/atest-desktop && npm i && npm run publish 21 | 22 | desktop-test: ## Run unit tests of the Electron Desktop 23 | cd console/atest-desktop && npm i && npm test 24 | -------------------------------------------------------------------------------- /tools/make/docs.mk: -------------------------------------------------------------------------------- 1 | # Building docs makefile defined. 2 | # 3 | # All make targets related to docs are defined in this file. 4 | 5 | DOCS_OUTPUT_DIR := site/public 6 | 7 | ##@ Docs 8 | 9 | .PHONY: docs 10 | docs: docs.clean 11 | @$(LOG_TARGET) 12 | cd $(ROOT_DIR)/docs/site && npm install 13 | cd $(ROOT_DIR)/docs/site && npm run build:production 14 | 15 | .PHONY: check-links 16 | check-links: ## Check for broken links in the docs. 17 | check-links: docs-check-links 18 | 19 | 20 | .PHONY: docs-check-links 21 | docs-check-links: 22 | @$(LOG_TARGET) 23 | # Check for broken links 24 | npm install -g linkinator@6.0.4 25 | # https://github.com/JustinBeckwith/linkinator?tab=readme-ov-file#command-usage 26 | linkinator docs/site/public -r --concurrency 25 -s "github.com _print v0.0.1" 27 | 28 | # Docs site, make by hexo. 29 | 30 | .PHONY: docs-serve 31 | docs-serve: ## Start API Testing Site Locally. 32 | @$(LOG_TARGET) 33 | cd $(ROOT_DIR)/docs/site && npm run serve 34 | 35 | .PHONY: docs-clean 36 | docs-clean: ## Remove all files that are created during builds. 37 | docs-clean: docs.clean 38 | 39 | .PHONY: docs.clean 40 | docs.clean: 41 | @$(LOG_TARGET) 42 | rm -rf $(DOCS_OUTPUT_DIR) 43 | rm -rf docs/site/node_modules 44 | rm -rf docs/site/resources 45 | rm -f docs/site/package-lock.json 46 | rm -f docs/site/.hugo_build.lock 47 | -------------------------------------------------------------------------------- /tools/make/env.mk: -------------------------------------------------------------------------------- 1 | # A wrapper to hold common environment variables used in other make wrappers 2 | # 3 | # This file does not contain any specific make targets. 4 | 5 | # Docker variables 6 | 7 | HELM_VERSION ?= v0.0.3 8 | 9 | # Docker repo 10 | REGISTRY ?= docker.io 11 | 12 | REGISTRY_NAMESPACE ?= linuxsuren 13 | 14 | # Set image tools 15 | IMAGE_TOOL ?= docker 16 | 17 | TOOLEXEC ?= #-toolexec="skywalking-go-agent" 18 | 19 | GOPROXY ?= direct 20 | 21 | TAG ?= ${REV} 22 | 23 | FRONT_RUNTIMES ?= npm 24 | -------------------------------------------------------------------------------- /tools/make/helm.mk: -------------------------------------------------------------------------------- 1 | # A wrapper to manage helm charts 2 | # 3 | # All make targets related to helmß are defined in this file. 4 | 5 | include tools/make/env.mk 6 | 7 | OCI_REGISTRY ?= oci://${REGISTRY}/${REGISTRY_NAMESPACE} 8 | 9 | CHART_NAME ?= api-testing 10 | CHART_VERSION ?= ${HELM_VERSION} 11 | 12 | ##@ Helm 13 | 14 | .PHONY: helm-pkg 15 | helm-pkg: ## Package API Testing helm chart. 16 | helm-pkg: helm-dev-update 17 | @$(LOG_TARGET) 18 | # e.g. api-testing-v0.0.3-helm.tgz 19 | helm package helm/${CHART_NAME} --version ${CHART_VERSION}-helm --app-version ${CHART_VERSION} --destination ${OUTPUT_DIR}/charts/ 20 | 21 | .PHONY: helm-push 22 | helm-push: 23 | helm-push: ## Push API Testing helm chart to OCI registry. 24 | @$(LOG_TARGET) 25 | helm push ${OUTPUT_DIR}/charts/${CHART_NAME}-${CHART_VERSION}-helm.tgz ${OCI_REGISTRY} 26 | 27 | .PHONY: helm-lint 28 | helm-lint: ## Helm lint API Testing helm chart. 29 | helm-lint: helm-dev-update 30 | helm lint helm/${CHART_NAME} 31 | 32 | helm-dev-update: 33 | helm-dev-update: 34 | helm dep update helm/${CHART_NAME} 35 | -------------------------------------------------------------------------------- /tools/make/image.mk: -------------------------------------------------------------------------------- 1 | # A wrapper to build and push docker image 2 | # 3 | # All make targets related to docker image are defined in this file. 4 | 5 | include tools/make/env.mk 6 | 7 | 8 | # Determine image files by looking into ./Dockerfile 9 | IMAGES_DIR ?= $(wildcard ${ROOT_DIR}tools/docker/*) 10 | # Determine images names by stripping out the dir names 11 | IMAGES ?= api-testing 12 | IMAGE_NAME ?= ${REGISTRY}/${REGISTRY_NAMESPACE}/${IMAGES}:${TAG} 13 | 14 | ifeq (${IMAGES},) 15 | $(error Could not determine IMAGES, set ROOT_DIR or run in source dir) 16 | endif 17 | 18 | .PHONY: image.build 19 | image.build: $(addprefix image.build., $(IMAGES)) 20 | 21 | .PHONY: image.build.% 22 | # Maybe can use: image.build.%: go.build.$(GOOS)_$(GOARCH).% 23 | # then to move binary file to docker context. 24 | image.build.%: 25 | @$(LOG_TARGET) 26 | @$(call log, "Building image $(GOOS)-$(GOARCH) $(IMAGES):$(TAG)") 27 | ${IMAGE_TOOL} build -f $(ROOT_DIR)/Dockerfile \ 28 | -t ${IMAGE_NAME} . \ 29 | --build-arg GOPROXY=${GOPROXY} \ 30 | --build-arg VERSION=$(TAG) 31 | 32 | .PHONY: run.image 33 | run.image: 34 | @$(LOG_TARGET) 35 | ${IMAGE_TOOL} run -p 7070:7070 -p 8080:8080 ${IMAGE_NAME} 36 | 37 | ##@ Image 38 | 39 | .PHONY: image 40 | image: ## Build docker images for host platform. See Option PLATFORM and IMAGES. 41 | image: image.build 42 | 43 | .PHONY: run-container 44 | run-container: ## Run the docker container for the image. See Option IMAGES and TAG. 45 | run-container: run.image 46 | -------------------------------------------------------------------------------- /tools/make/lint.mk: -------------------------------------------------------------------------------- 1 | # A wrapper to do lint checks 2 | # 3 | # All make targets related to lint are defined in this file. 4 | 5 | ##@ Lint 6 | 7 | GITHUB_ACTION ?= 8 | 9 | .PHONY: lint 10 | lint: ## Run all linter of code sources, including golint, yamllint. 11 | 12 | # lint-deps is run separately in CI to separate the tooling install logs from the actual output logs generated 13 | # by the lint tooling. 14 | .PHONY: lint-deps 15 | lint-deps: ## Everything necessary to lint 16 | 17 | GOLANGCI_LINT_FLAGS ?= $(if $(GITHUB_ACTION),--out-format=github-actions) 18 | 19 | .PHONY: lint.golint 20 | lint: lint.golint 21 | lint-deps: $(tools/golangci-lint) 22 | lint.golint: $(tools/golangci-lint) 23 | @$(LOG_TARGET) 24 | $(tools/golangci-lint) run $(GOLANGCI_LINT_FLAGS) --build-tags=e2e,celvalidation --config=tools/linter/golangci-lint/.golangci.yml 25 | 26 | .PHONY: lint.yamllint 27 | lint: lint.yamllint 28 | lint-deps: $(tools/yamllint) 29 | lint.yamllint: $(tools/yamllint) 30 | @$(LOG_TARGET) 31 | $(tools/yamllint) --config-file=tools/linter/yamllint/.yamllint $$(git ls-files :*.yml :*.yaml | xargs -L1 dirname | sort -u) 32 | -------------------------------------------------------------------------------- /tools/make/test.mk: -------------------------------------------------------------------------------- 1 | # A wrapper to test. 2 | # 3 | # All make targets related to e2e,full test are defined in this file. 4 | 5 | .PHONY: test.e2e 6 | test.e2e: 7 | cd e2e && ./start.sh && ./start.sh compose-k8s.yaml && ./start.sh compose-external.yaml 8 | 9 | .PHONY: test.fuzz 10 | test.fuzz: 11 | cd pkg/util && go test -fuzz FuzzZeroThenDefault -fuzztime 6s 12 | 13 | ##@ Other Test 14 | 15 | .PHONY: test-e2e 16 | test-e2e: ## Run e2e tests 17 | test-e2e: test.e2e 18 | 19 | .PHONY: full-test-e2e 20 | full-test-e2e: ## Build image then run e2e tests 21 | full-test-e2e: 22 | TAG=master REGISTRY=ghcr.io make image test-e2e 23 | 24 | .PHONY: test-fuzz 25 | test-fuzz: ## Run fuzz tests 26 | test-fuzz: test.fuzz 27 | -------------------------------------------------------------------------------- /tools/src/golangci-lint/pin.go: -------------------------------------------------------------------------------- 1 | //go:build pin 2 | // +build pin 3 | 4 | /* 5 | Copyright 2024 API Testing Authors. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package ignore 21 | 22 | import _ "github.com/golangci/golangci-lint/cmd/golangci-lint" 23 | -------------------------------------------------------------------------------- /tools/src/yamllint/requirements.txt: -------------------------------------------------------------------------------- 1 | yamllint==1.35.1 2 | --------------------------------------------------------------------------------