{"id":13413868,"url":"https://github.com/viant/endly","last_synced_at":"2026-01-07T22:14:55.444Z","repository":{"id":41432282,"uuid":"101684579","full_name":"viant/endly","owner":"viant","description":"End to end functional test and automation framework","archived":false,"fork":false,"pushed_at":"2025-04-28T21:43:44.000Z","size":32202,"stargazers_count":266,"open_issues_count":3,"forks_count":35,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-05-16T10:04:35.736Z","etag":null,"topics":["automation","end-to-end-testing","functional-testing","integration-testing","orchestration-framework","system-testing","testing","workflow"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/viant.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-08-28T20:24:43.000Z","updated_at":"2025-04-29T06:22:56.000Z","dependencies_parsed_at":"2024-06-05T23:59:05.262Z","dependency_job_id":"941411bc-9461-4c3f-b0fa-73365c176589","html_url":"https://github.com/viant/endly","commit_stats":{"total_commits":2390,"total_committers":28,"mean_commits":85.35714285714286,"dds":"0.14937238493723848","last_synced_commit":"90e74f92f1139ec6ad443795a5ef48163d5b34e9"},"previous_names":[],"tags_count":74,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viant%2Fendly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viant%2Fendly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viant%2Fendly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/viant%2Fendly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/viant","download_url":"https://codeload.github.com/viant/endly/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254509476,"owners_count":22082891,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","end-to-end-testing","functional-testing","integration-testing","orchestration-framework","system-testing","testing","workflow"],"created_at":"2024-07-30T20:01:51.561Z","updated_at":"2026-01-07T22:14:55.390Z","avatar_url":"https://github.com/viant.png","language":"Go","readme":"# Declarative end to end functional testing (endly)\n\n[![Declarative funtional testing for Go.](https://goreportcard.com/badge/github.com/viant/endly)](https://goreportcard.com/report/github.com/viant/endly)\n[![GoDoc](https://godoc.org/github.com/viant/endly?status.svg)](https://godoc.org/github.com/viant/endly)\n\nThis library is compatible with Go 1.12+\n\nPlease refer to [`CHANGELOG.md`](CHANGELOG.md) if you encounter breaking changes.\n\n- [Motivation](#motivation)\n- [Introduction](#introduction)\n- [Getting Started](#getting-started)\n- [Documentation](#documentation)\n- [License](#license)\n\n- [Credits and Acknowledgements](#credits-and-acknowledgements)\n\n\n## Motivation\n\nEndly is comprehensive workflow based automation and end-to-end (E2E) testing tool designed to simulate a production environment as closely as possible. \nThis includes the full spectrum of network communications, user interactions, data storage, and other dependencies. \nBy doing so, it aims to ensure that systems are thoroughly tested under conditions that mimic real-world operations, \nhelping to identify and address potential issues before deployment.\n\n## Introduction\n\nEndly is a highly versatile automation and orchestration platform that provides a wide range of services to support various aspects of software development, \ntesting, deployment, and operations. \n\nBelow is a summary of the types of services Endly can orchestrate, grouped by their primary functionality:\n\n### Platform, Infrastructure and Cloud Providers:\n\n- Docker([docker](service/system/docker)): Provides services for managing Docker containers and executing commands over SSH within Docker environments,\n  enhancing container management and deployment.\n- AWS Services([aws/*](service/system/cloud/aws)): Offers orchestration for numerous AWS services, including API Gateway, CloudWatch, DynamoDB, EC2, IAM,\n  Kinesis, KMS, Lambda, RDS, S3, SES, SNS, SQS, and SSM. These services enable management and automation of AWS\n  resources, monitoring, notification, and security.\n- GCP Services([gcp/*](service/system/cloud/gcp)): Supports Google Cloud Platform resources such as BigQuery, Cloud Functions, Cloud Scheduler, Compute\n  Engine, GKE (Google Kubernetes Engine), KMS, Pub/Sub, Cloud Run, and Cloud Storage. These services are essential for\n  managing Google Cloud resources, data analysis, event-driven computing, and storage.\n\n###  Environment/System Management\n\n- Exec([exec](service/system/exec)): This service is central to executing shell commands, allowing for automation of tasks that interact directly\n  with the operating system. This capability is essential for setting up environments, running scripts, and performing\n  system-level operations, thereby serving as a foundation for environment and system management within Endly's\n  orchestration capabilities.\n- Process([process](service/system/process)): Manages processes or daemons on the system, enabling control over the lifecycle of various applications or\n  services running in the background. This service is key for ensuring that necessary services are operational during\n  testing or deployment, and for automating start, stop, and restart operations of system services as part of\n  environment setup and maintenance.\n- Storage([storage](service/system/storage)): Facilitates the management of file-based assets, including uploading, downloading, and managing files. This\n  service is crucial for handling configuration files, test data, and other file-based resources needed throughout the\n  automation, testing, and deployment processes. It supports the simulation of real-world environments by ensuring the\n  correct setup of file systems and data storage scenarios.\n- Secret([secret](service/system/secret)): Manages safe access to secrets, such as passwords and API keys, crucial for maintaining security in automated\n  processes.\n\n###  Development and Deployment\n\n- Version control([vc](service/deployment/vc)) service to manage source code.\n- SDK([sdk](service/deployment/sdk)) service for setting specific sdk (go/node)\n\n### Database and Data Management\n\n- DSUnit([dsunit](service/testing/dsunit)): Facilitates database testing, supporting the setup and teardown of database states for testing purposes.\n\n### Testing and Integration\n\n- HTTP/REST([http/runner](service/testing/runner/http)): Provides tools for testing and interacting with HTTP endpoints and RESTful APIs. This service is\n  instrumental in API testing, allowing for the automation of requests, response validation, and the simulation of\n  various API usage scenarios. It supports both the verification of external services and the testing of application\n  interfaces, making it a vital component for ensuring the functionality and reliability of web services and\n  applications. In addition, runner allows can be used as load testing tool, enabling the simulation of high traffic scenarios to evaluate system\n  performance and scalability. This service is essential for assessing the robustness of applications under heavy loads\n  and for identifying performance bottlenecks that may arise in production environments.\n- HTTP/Endpoint([http/endpoint](service/testing/endpoint/http)): This service extends Endly's capabilities into the realm of HTTP communication testing by allowing\n  users to listen to existing HTTP interactions, record them, and subsequently mock these interactions for the purpose\n  of testing. This functionality is particularly useful for simulating third-party HTTP integrations without the need\n  for the third-party services to be actively involved in the testing process. By capturing and replicating the behavior\n  of external HTTP services, it enables developers to conduct thorough testing of application integrations in a\n  controlled, predictable environment. This approach ensures that applications can gracefully handle external HTTP\n  requests and responses, facilitating the validation of integration points with external APIs and services. The ability\n  to mock external HTTP interactions is invaluable for continuous integration and testing workflows, where external\n  dependencies must be accurately simulated to verify application functionality and resilience.\n- WebDrvier([webdriver](service/testing/runner/webdriver)): Supports browser-based testing and automation, essential for web application testing.\n- Validator([validator](service/testing/validator)): Provides validation services, including log validation, to ensure that applications behave as expected.\n- Postman ([migration/postman](service/migration/postman)): Service for migrating postman scripts into endly workflow.\n- Rest([rest](service/testing/runner/rest)): Service for testing REST API.\n\n\nCommunication and Messaging\n\n- Message Bus([msg](service/testing/msg)): Universal message bus service for testing queue, topic and subscription\n- SMTP ([smtp](service/notify/smtp)):  Service for sending emails.\n- Slack  ([slack](service/notify/slack)): Services for sending Slack messages, enabling notifications and alerts as part of the\n  automation workflows.\n\nEndly is open source project to check the latest list of endly supported service run on terminal:\n\n```endly -s='*'```\n\n\n## Getting Started\n\n\n##### Installation\n  - [Install/Download](doc/installation)\n  - [Endly docker image](docker/)\n\n\n\n##### Examples:\n\n\n**a) Infrastructure/Environment preparation**\n\nFor instance: the following define inline workflow to prepare app system services:\n\n@system.yaml\n```yaml\ntasks: $tasks\ndefaults:\n  target: $serviceTarget\npipeline:\n  destroy:\n    stop-images:\n      action: docker:stop\n      images:\n        - mysql\n        - aerospike\n  init:\n    services:\n      mysql:\n        workflow: \"service/mysql:start\"\n        name: mydb3\n        version: $mysqlVersion\n        credentials: $mysqlCredentials\n        config: config/my.cnf\n      aerospike:\n        workflow: \"service/aerospike:start\"\n        name: mydb4\n        config: config/aerospike.conf\n```\n\n\n**b) Application build and deployment** \n\nFor instance: the following  define inline workflow to build and deploy a test app:\n(you can easily build an app for standalone mode or in and for docker container)\n\n\n**With Dockerfile build file and docker compose**\n\n@app.yaml\n```yaml\ntasks: $tasks\ninit:\n- buildPath = /tmp/build/myapp/\n- version = 0.1.0\ndefaults:\n  app: myapp\n  version: 0.1.0\n  useRegistry: false\npipeline:\n  build:\n    init:\n      action: exec:run\n      target: $target\n      commands:\n      - if [ -e $buildPath ]; then rm -rf $buildPath; fi\n      - mkdir -p $buildPath\n    checkout:\n      action: version/control:checkout\n      origin:\n        URL: https://github.com/adrianwit/dstransfer\n      dest:\n        URL: scp://${targetHost}:22/$buildPath\n        credentials: localhost\n    download:\n      action: storage:copy\n      source:\n        URL: config/Dockerfile\n      dest:\n        URL: $buildPath\n        credentials: localhost\n    build-img:\n      action: docker:build\n      target: $target\n      path: $buildPath\n      '@tag':\n        image: dstransfer\n        username: adrianwit\n        version: 0.1.0\n  stop:\n    target: $appTarget\n    action: docker/ssh:composeDown\n    source:\n      URL: config/docker-compose.yaml\n  deploy:\n    target: $appTarget\n    action: docker/ssh:composeUp\n    runInBackground: true\n    source:\n      URL: config/docker-compose.yaml\n\n```\n\n**As Standalone app** (with predefined shared workflow)\n\n\n@app.yaml\n```yaml\ninit:\n  buildTarget:\n    URL: scp://127.0.0.1/tmp/build/myApp/\n    credentials: localhost\n  appTarget:\n    URL: scp://127.0.0.1/opt/myApp/\n    credentials: localhost\n  target:\n    URL: scp://127.0.0.1/\n    credentials: localhost\ndefaults:\n  target: $target\n\npipeline:\n\n  build:\n    checkout:\n      action: version/control:checkout\n      origin:\n        URL: ./../ \n        #or https://github.com/myRepo/myApp\n      dest: $buildTarget\n    set-sdk:\n      action: sdk:set\n      sdk: go:1.17\n    build-app:\n      action: exec:run\n      commands:\n        - cd /tmp/build/myApp/app\n        - export GO111MODULE=on\n        - go build myApp.go\n        - chmod +x myApp\n    deploy:\n      mkdir:\n        action: exec:run\n        commands:\n          - sudo rm -rf /opt/myApp/\n          - sudo mkdir -p /opt/myApp\n          - sudo chown -R ${os.user} /opt/myApp\n\n      install:\n        action: storage:copy\n        source: $buildTarget\n        dest: $appTarget\n        expand: true\n        assets:\n          app/myApp: myApp\n          config/config.json: config.json\n\n  stop:\n    action: process:stop\n    input: myApp\n\n  start:\n    action: process:start\n    directory: /opt/myApp\n    immuneToHangups: true\n    command: ./myApp\n    arguments:\n      - \"-config\"\n      - \"config.json\"\n\n```\n\n**c) Datastore/database creation**\n\nFor instance: the following  define inline workflow to create/populare mysql and aerospike database/dataset:\n\n@datastore.yaml\n\n```yaml\npipeline:\n  create-db:\n    db3:\n      action: dsunit:init\n      scripts:\n        - URL: datastore/db3/schema.ddl\n      datastore: db3\n      recreate: true\n      config:\n        driverName: mysql\n        descriptor: \"[username]:[password]@tcp(127.0.0.1:3306)/[dbname]?parseTime=true\"\n        credentials: $mysqlCredentials\n      admin:\n        datastore: mysql\n        config:\n          driverName: mysql\n          descriptor: \"[username]:[password]@tcp(127.0.0.1:3306)/[dbname]?parseTime=true\"\n          credentials: $mysqlCredentials\n    db4:\n      action: dsunit:init\n      datastore: db4\n      recreate: true\n      config:\n        driverName: aerospike\n        descriptor: \"tcp([host]:3000)/[namespace]\"\n        parameters:\n          dbname: db4\n          namespace: db4\n          host: $serviceHost\n          port: 3000\n  populate:\n    db3:\n      action: dsunit:prepare\n      datastore: db3\n      URL: datastore/db3/dictionary\n    db4:\n      action: dsunit:prepare\n      datastore: db4\n      URL: datastore/db4/data\n```\n\n```bash\nendly -r=datastore\n```\n\n**d) Creating setup / verification dataset from existing datastore**\n\n\nFor instance: the following  define inline workflow to create setup dataset SQL based from on existing database\n\n@freeze.yaml\n```yaml\npipeline:\n  db1:\n    register:\n      action: dsunit:register\n      datastore: db1\n      config:\n        driverName: bigquery\n        credentials: bq\n        parameters:\n          datasetId: adlogs\n\n    reverse:\n      takeSchemaSnapshot:\n        action: dsunit:dump\n        datastore: db1\n        # leave empty for all tables\n        tables:\n          - raw_logs\n        #optionally target for target vendor if different that source  \n        target: mysql \n        destURL: schema.sql\n        \n      takeDataSnapshot:\n        action: dsunit:freeze\n        datastore: db1\n        destURL: db1/prepare/raw_logs.json\n        omitEmpty: true\n        ignore:\n          - request.postBody\n        replace:\n          request.timestamp: $$ts\n        sql:  SELECT request, meta, fee\n                FROM raw_logs \n                WHERE requests.sessionID IN(x, y, z)\n```\n\n```bash\nendly -r=freeze\n```\n\n\n**e) Comparing SQL based data sets**\n\n```bash\nendly -r=compare\n```\n\n@compare.yaml\n```yaml\npipeline:\n  register:\n    verticadb:\n      action: dsunit:register\n      datastore: db1\n      config:\n        driverName: odbc\n        descriptor: driver=Vertica;Database=[database];ServerName=[server];port=5433;user=[username];password=[password]\n        credentials: db1\n        parameters:\n          database: db1\n          server: x.y.z.a\n          TIMEZONE: UTC\n    bigquerydb:\n      action: dsunit:register\n      datastore: db2\n      config:\n        driverName: bigquery\n        credentials: db2\n        parameters:\n          datasetId: db2\n  compare:\n    action: dsunit:compare\n    maxRowDiscrepancy: 10\n    ignore:\n      - field10\n      - fieldN\n    directives:\n      \"@numericPrecisionPoint@\": 7\n      \"@coalesceWithZero@\": true\n      \"@caseSensitive@\": false\n    \n    source1:\n      datastore: db1\n      SQL: SELECT * \n           FROM db1.mytable \n           WHERE DATE(ts) BETWEEN '2018-12-01' AND '2018-12-02' \n           ORDER BY 1\n\n    source2:\n      datastore: db2\n      SQL: SELECT *\n           FROM db2.mytable\n           WHERE DATE(ts) BETWEEN '2018-12-01' AND '2018-12-02'\n           ORDER BY 1\n```\n\n\n**f) Testing**\n\nFor instance: the following  define inline workflow to run test with selenium runner:\n\n\n@test.yaml\n\n```yaml\ndefaults:\n  target:\n     URL: ssh://127.0.0.1/\n     credentials: localhost\npipeline:\n  init:\n    action: selenium:start\n    version: 3.4.0\n    port: 8085\n    sdk: jdk\n    sdkVersion: 1.8\n  test:\n    action: selenium:run\n    browser: firefox\n    remoteSelenium:\n      URL: http://127.0.0.1:8085\n    commands:\n      - get(http://play.golang.org/?simple=1)\n      - (#code).clear\n      - (#code).sendKeys(package main\n\n          import \"fmt\"\n\n          func main() {\n              fmt.Println(\"Hello Endly!\")\n          }\n        )\n      - (#run).click\n      - command: output = (#output).text\n        exit: $output.Text:/Endly/\n        sleepTimeMs: 1000\n        repeat: 10\n      - close\n    expect:\n      output:\n        Text: /Hello Endly!/\n```\n\n```bash\nendly -r=test\n```\n\n\n**g) Stress testing:**\n\nThe following  define inline workflow that loads request and desired responses from data folder for stress testing.\n\n@load.yaml\n```yaml\ninit:\n  testEndpoint: z.myendoint.com\npipeline:\n  test:\n    tag: StressTest\n    data:\n      []Requests: '@data/*request.json'\n      []Responses: '@data/*response.json'\n    range: '1..1'\n    template:\n      info:\n        action: print\n        message: starting load testing \n      load:\n        action: 'http/runner:load'\n        threadCount: 3\n        '@repeat': 100\n        requests: $data.Requests\n        expect:\n          Responses: $data.Responses\n      load-info:\n        action: print\n        message: 'QPS: $load.QPS: Response: min: $load.MinResponseTimeInMs ms, avg: $load.AvgResponseTimeInMs ms max: $load.MaxResponseTimeInMs ms'\n\n```\n\nWhere data folder contains http request and desired responses i.e \n\n@data/XXX_request.json\n```json\n{\n  \"Method\":\"get\",\n  \"URL\":\"http://${testEndpoint}/bg/?pixid=123\"\n}\n```\n\n@data/XXX_response.json\n```json\n{\n  \"Code\":200,\n  \"Body\":\"/some expected fragement/\"\n}\n```\n\n\n```bash\nendly -r=load\n```\n\n\n\n**h) Serverless e2e testing with cloud function**\n\n\n@test.yaml\n```yaml\ndefaults:\n  credentials: am\npipeline:\n  deploy:\n    action: gcp/cloudfunctions:deploy\n    '@name': HelloWorld\n    entryPoint: HelloWorldFn\n    runtime: go111\n    source:\n      URL: test/\n  test:\n    action: gcp/cloudfunctions:call\n    logging: false\n    '@name': HelloWorld\n    data:\n      from: Endly\n  info:\n    action: print\n    message: $test.Result\n  assert:\n    action: validator:assert\n    expect: /Endly/\n    actual: $test.Result\n  undeploy:\n    action: gcp/cloudfunctions:delete\n    '@name': HelloWorld\n\n```\n\n**i) Serverless e2e testing with lambda function**\n\n@test.yaml\n```yaml\ninit:\n  functionRole: lambda-loginfo-executor\n  functionName: LoginfoFn\n  codeZip: ${appPath}/loginfo/app/loginfo.zip\n  privilegePolicy: ${parent.path}/privilege-policy.json\npipeline:\n  deploy:\n    build:\n      action: exec:run\n      target: $target\n      errors:\n        - ERROR\n      commands:\n        - cd ${appPath}loginfo/app\n        - unset GOPATH\n        - export GOOS=linux\n        - export GOARCH=amd64\n        - go build -o loginfo\n        - zip -j loginfo.zip loginfo\n\n    setupFunction:\n      action: aws/lambda:deploy\n      credentials: $awsCredentials\n      functionname: $functionName\n      runtime:  go1.x\n      handler: loginfo\n      code:\n        zipfile: $LoadBinary(${codeZip})\n      rolename: lambda-loginfo-executor\n      define:\n        - policyname: s3-mye2e-bucket-role\n          policydocument: $Cat('${privilegePolicy}')\n      attach:\n        - policyarn: arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole\n\n    setupAPI:\n      action: aws/apigateway:deployAPI\n      credentials: aws\n      '@name': loginfoAPI\n      resources:\n        - path: /{proxy+}\n          methods:\n            - httpMethod: ANY\n              functionname: $functionName\n    sleepTimeMs: 10000\n\n  test:\n    action: rest/runner:send\n    URL: ${setupAPI.EndpointURL}oginfo\n    method: post\n     '@request':\n      region: ${awsSecrets.Region}\n      URL: s3://mye2e-bucket/folder1/\n    expect:\n      Status: ok\n      FileCount: 2\n      LinesCount: 52\n\n```\n\nTo see _Endly_ in action,\n### End to end testing examples\n \nIn addition a few examples of fully functioning applications are included.\nYou can build, deploy and test them end to end all with endly.\n\n \n1) **Web Service** \n   * [Reporter](example/ws/reporter) - a pivot table report builder.\n        - Test with Rest Runner\n        - Data Preparation and Validation (mysql)\n        \n2) **User Interface**\n   * [SSO](example/ui/sso)  - user registration and login application.\n        - Test with Selenium Runner\n        - Test with HTTP Runner\n        - Data Preparation and Validation (aersopike)\n        - Web Content validation\n        - Mocking 3rd party REST API with [http/endpoint service](testing/endpoint/http) \n        \n3) **Extract, Transform and Load (ETL)**\n   * [Transformer](example/etl/myApp) - datastore to datastore myApp (i.e. aerospike to mysql)\n       - Test with Rest Runner\n       - Data Preparation and Validation (aersopike, mysql)\n\n4) **Runtime**  - simple http request event logger\n   * [Logger](example/rt/elogger)\n       - Test with HTTP Runner\n       - Log Validation\n\n5) **Serverless**  - serverless (lambda/cloud function/dataflow)\n   * [Serverless](https://github.com/adrianwit/serverless_e2e)\n    \n    \n\n\u003ca name=\"Documentation\"\u003e\u003c/a\u003e\n\n## Documentation\n- [Installation](doc/installation)\n- [Secret/Credential](doc/secrets)\n- [Inline Workflow](doc/inline)\n- [Workflow](doc/workflow)\n- [Service](doc/service)\n- [Usage](doc/usage)\n- [User Defined Function](doc/udf)\n- [Data store testing](testing/dsunit)\n\n\n\n@run.yaml\n```yaml\ntarget:\n  URL: \"ssh://127.0.0.1/\"\n  credentials: localhost\nsystemPaths:\n  - /usr/local/go/bin\ncommands:\n  - go version\n  - echo $GOPATH\n```\n\n## External resources\n\n- [Endly introduction](https://github.com/adrianwit/endly-introduction)\n- [Software Developement Automation - Part I](https://medium.com/@adrianwit/software-development-automation-e68b3bcc70c9?)\n- [Software Developement Automation - Part II](https://medium.com/@adrianwit/software-development-automation-part-ii-bf961cfdd88a)\n- [ETL end to end testing with docker, NoSQL, RDBMS and Big Query](https://medium.com/@adrianwit/etl-end-to-end-testing-with-docker-nosql-rdbms-and-big-query-35b13b7fada8)\n- [Data testing strategy reinvented](https://medium.com/@adrianwit/killing-data-testing-swamp-6c3e11fb92c6)\n- [Go lang e2e testing](https://github.com/adrianwit/golang-e2e-testing)\n- [Endly UI e2e testing demo](https://www.youtube.com/watch?v=W6R4lk_iF0k\u0026t=12s)\n\n         \t\n## License\n\nThe source code is made available under the terms of the Apache License, Version 2, as stated in the file `LICENSE`.\n\nIndividual files may be made available under their own specific license,\nall compatible with Apache License, Version 2. Please see individual files for details.\n\n\n## TODO\n\n- [ ] documentation improvements\n- [ ] command executor with os/exec.Command\n- [ ] gcp/containers integration\n- [ ] gcp/cloudfunctions viant/afs integration\n- [ ] ufd self describing meta data\n- [ ] viant/afs docker connector\n\n\n## Contributing to endly\n\nendly is an open source project and contributors are welcome!\n\n\n##  Credits and Acknowledgements\n\n  **Library Author:** Adrian Witas\n\n","funding_links":[],"categories":["Testing","Template Engines","开源类库","Open source library","Go","Testing Frameworks","测试","测试相关`测试库和测试数据集生成库`","测试相关","Resources"],"sub_categories":["Testing Frameworks","测试","Test","交流","HTTP Clients","HTTP客户端","查询语","Advanced Console UIs"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviant%2Fendly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fviant%2Fendly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviant%2Fendly/lists"}