{"id":15044583,"url":"https://github.com/sskorol/test-data-supplier","last_synced_at":"2025-04-09T19:19:54.779Z","repository":{"id":37851209,"uuid":"95954833","full_name":"sskorol/test-data-supplier","owner":"sskorol","description":"TestNG DataProvider on steroids","archived":false,"fork":false,"pushed_at":"2024-04-08T14:26:38.000Z","size":674,"stargazers_count":145,"open_issues_count":2,"forks_count":24,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-04-09T19:19:50.291Z","etag":null,"topics":["aqa","automation","data-driven","data-driven-tests","dataprovider","datasupplier","ddt","java","java17","qa","qaa","quality","quality-assurance","test-automation","test-data","test-data-supplier","testing","testng"],"latest_commit_sha":null,"homepage":"","language":"Java","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/sskorol.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-01T09:29:17.000Z","updated_at":"2024-12-12T20:49:15.000Z","dependencies_parsed_at":"2023-02-18T07:45:45.500Z","dependency_job_id":"7797234b-1ebd-4761-bcbb-c32c1d69f054","html_url":"https://github.com/sskorol/test-data-supplier","commit_stats":{"total_commits":241,"total_committers":3,"mean_commits":80.33333333333333,"dds":"0.17427385892116187","last_synced_commit":"eb8bcae48783364a57d52b1c6c557ec4c8bf049d"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sskorol%2Ftest-data-supplier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sskorol%2Ftest-data-supplier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sskorol%2Ftest-data-supplier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sskorol%2Ftest-data-supplier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sskorol","download_url":"https://codeload.github.com/sskorol/test-data-supplier/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248094991,"owners_count":21046770,"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":["aqa","automation","data-driven","data-driven-tests","dataprovider","datasupplier","ddt","java","java17","qa","qaa","quality","quality-assurance","test-automation","test-data","test-data-supplier","testing","testng"],"created_at":"2024-09-24T20:50:45.567Z","updated_at":"2025-04-09T19:19:54.752Z","avatar_url":"https://github.com/sskorol.png","language":"Java","funding_links":[],"categories":["测试"],"sub_categories":[],"readme":"# Test Data Supplier \n\n[![Build Status](https://github.com/sskorol/test-data-supplier/actions/workflows/ci.yml/badge.svg?branch=main\u0026event=push)](https://github.com/sskorol/test-data-supplier/actions/workflows/ci.yml)\n[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=io.github.sskorol%3Atest-data-supplier\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=io.github.sskorol%3Atest-data-supplier)\n[![Code Coverage](https://sonarcloud.io/api/project_badges/measure?project=io.github.sskorol%3Atest-data-supplier\u0026metric=coverage)](https://sonarcloud.io/component_measures?id=io.github.sskorol%3Atest-data-supplier\u0026metric=coverage)\n[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=io.github.sskorol%3Atest-data-supplier\u0026metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=io.github.sskorol%3Atest-data-supplier)\n[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=io.github.sskorol%3Atest-data-supplier\u0026metric=bugs)](https://sonarcloud.io/summary/new_code?id=io.github.sskorol%3Atest-data-supplier)\n[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=io.github.sskorol%3Atest-data-supplier\u0026metric=code_smells)](https://sonarcloud.io/summary/new_code?id=io.github.sskorol%3Atest-data-supplier)\n[![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=io.github.sskorol%3Atest-data-supplier\u0026metric=sqale_index)](https://sonarcloud.io/summary/new_code?id=io.github.sskorol%3Atest-data-supplier)\n[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=io.github.sskorol%3Atest-data-supplier\u0026metric=security_rating)](https://sonarcloud.io/summary/new_code?id=io.github.sskorol%3Atest-data-supplier)\n[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=io.github.sskorol%3Atest-data-supplier\u0026metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=io.github.sskorol%3Atest-data-supplier)\n[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=io.github.sskorol%3Atest-data-supplier\u0026metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=io.github.sskorol%3Atest-data-supplier)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.sskorol/test-data-supplier/badge.svg?style=flat)](https://maven-badges.herokuapp.com/maven-central/io.github.sskorol/test-data-supplier)\n[![GitHub license](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://goo.gl/9GLmMZ)\n[![Twitter](https://img.shields.io/twitter/url/https/github.com/sskorol/test-data-supplier.svg?style=social)](https://twitter.com/intent/tweet?text=Check%20new%20Test%20Data%20Supplier%20library:\u0026url=https://github.com/sskorol/test-data-supplier)\n\n## Table of Contents\n\n- [Description](#description)\n- [Supported Flags](#supported-flags)\n- [Supported Return Types](#supported-return-types)\n- [Usage](#usage)\n  - [Gradle - Java \u003c 9](#gradle---java--9)\n  - [Maven - Java \u003c 9](#maven---java--9)\n  - [Gradle - Java 11-16 w/o modules](#gradle---java-11-16-wo-modules)\n  - [Gradle - Java 11-16 w/ modules](#gradle---java-11-16-w-modules)\n  - [Gradle - Java 17+ w/o modules](#gradle---java-17-wo-modules)\n  - [Maven - Java 17+ w/o modules](#maven---java-17-wo-modules)\n  - [API](#api)\n  - [JSON, CSV, YAML and XLSX processors](#json-csv-yaml-and-xlsx-processors)\n  - [DB support](#db-support)\n  - [Factory](#factory)\n  - [Tracking meta-data](#tracking-meta-data)\n  - [IAnnotationTransformer restriction](#iannotationtransformer-restriction)\n- [IntelliJ IDEA support](#intellij-idea-support) \n\n## Description\n\n\u003cdiv\u003e\u003cvideo src=\"https://github.com/sskorol/sskorol/assets/6638780/8a11ad45-10a8-4e60-8d79-dbb723137762\"/\u003e\u003c/div\u003e\n\nThis repository contains TestNG **DataProvider** wrapper (the latest version is based on TestNG 7.7.1) which helps to supply test data in a more flexible way.\n\nCommon **DataProvider** forces using quite old and ugly syntax which expects one of the following types to be returned from DP method's body:\n\n - Object[][]\n - Iterator\u003cObject[]\u003e\n\nThat's weird as developers tend to use `Stream` and `Collection` API for data manipulation in the modern Java world.\n\nJust imagine if you could use the following syntax to supply some filtered and sorted data into test method's signature:\n\n```java\n@DataSupplier\npublic Stream\u003cUser\u003e getData() {\n    return Stream\n        .of(\n            new User(\"Max\", \"password2\"),\n            new User(\"Black Fox\", \"password3\"),\n            new User(\"Mark\", \"password1\")\n        )\n        .filter(u -\u003e !u.getName().contains(\"Fox\"))\n        .sorted(comparing(User::getPassword));\n}\n    \n@Test(dataProvider = \"getData\")\npublic void shouldSupplyStreamData(final User user) {\n    // ...\n}\n```\n\nMuch better and flexible than two-dimensional arrays or iterators, isn't it?\n\nAnd what if we don't want to iterate the same test N times depending on collection size? What if we want to inject it into test's signature like the following?\n\n```java\n@DataSupplier(transpose = true)\npublic List\u003cUser\u003e getTransposedData() {\n    return StreamEx\n        .of(\n            new User(\"username1\", \"password1\"),\n            new User(\"username2\", \"password2\")\n        )\n        .toList();\n}\n        \n@Test(dataProvider = \"getTransposedData\")\npublic void shouldSupplyExtractedListData(final List\u003cUser\u003e users) {\n    // ...\n}\n```\n\nOr if you want to extract the values of your collection and inject into test's signature, you can combine `transpose` with a `flatMap`:\n\n```java\n@DataSupplier(transpose = true, flatMap = true)\npublic Set\u003cUser\u003e getExtractedData() {\n    return StreamEx.of(\"product1\", \"product2\", \"product1\").toSet();\n}\n        \n@Test(dataProvider = \"getExtractedData\")\npublic void shouldSupplyExtractedListData(final String... products) {\n    // ...\n}\n```\n\nJava-like **flatMap** operation can be applied even to more complicated structures like `Map` to extract values for each row:\n\n```java\n@DataSupplier(flatMap = true)\npublic Map\u003cInteger, String\u003e getInternallyExtractedMapData() {\n    return EntryStream.of(asList(\"user3\", \"user4\")).toMap();\n}\n    \n@Test(dataProvider = \"getInternallyExtractedMapData\")\npublic void supplyInternallyExtractedMapData(final Integer key, final String value) {\n    // not implemented\n}\n```\n\n[**Go top**](#test-data-supplier) :point_up:\n\n## Supported flags\n\n- **name**: sets a custom name for `DataSupplier` (method name is used by default)\n- **transpose**: translates data column into a single row\n- **flatMap**: behaves pretty much like a native Java Stream operation\n- **runInParallel**: executes each data-driven test in parallel rather than sequentially\n- **indices**: filters the underlying collection by given indices\n- **propagateTestFailure**: fails the test in case of `DataSupplier` failure (skips by default)\n\n[**Go top**](#test-data-supplier) :point_up:\n\n## Supported return types\n\n - Collection\n - Map\n - Entry\n - Object[]\n - double[]\n - int[]\n - long[]\n - Stream / StreamEx \n - Tuple\n - A single Object of any common or custom type\n\n[**Go top**](#test-data-supplier) :point_up:\n\n## Usage\n\n### Gradle - Java \u003c 9\n\nAdd the following configuration into **build.gradle**:\n\n```groovy\nrepositories {\n    mavenCentral()\n}\n    \nconfigurations {\n    agent\n}\n\nsourceCompatibility = JavaVersion.VERSION_1_8\n\next {\n    aspectjVersion = '1.9.7'\n}\n\n[compileJava, compileTestJava]*.options*.compilerArgs = ['-parameters']\n    \ndependencies {\n    agent \"org.aspectj:aspectjweaver:${aspectjVersion}\"\n    implementation(\n            \"org.aspectj:aspectjweaver:${aspectjVersion}\",\n            'org.testng:testng:6.14.3',\n            'io.github.sskorol:test-data-supplier:1.7.0'\n    )\n}\n    \ntest {\n    doFirst {\n        jvmArgs(\"-javaagent:${configurations.agent.singleFile}\")\n    }\n    \n    useTestNG()\n}\n```\n\nCheck a separate [project](https://github.com/sskorol/test-data-supplier-gradle-example) with usage examples.\n\n[**Go top**](#test-data-supplier) :point_up:\n\n### Maven - Java \u003c 9\n\nAdd the following configuration into **pom.xml**:\n\n```xml\n\u003cproperties\u003e\n    \u003caspectj.version\u003e1.9.7\u003c/aspectj.version\u003e\n    \u003cjava.version\u003e1.8\u003c/java.version\u003e\n    \u003ccompiler.plugin.version\u003e3.8.0\u003c/compiler.plugin.version\u003e\n    \u003csurefire.plugin.version\u003e2.20.1\u003c/surefire.plugin.version\u003e\n\u003c/properties\u003e\n    \n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.aspectj\u003c/groupId\u003e\n        \u003cartifactId\u003easpectjweaver\u003c/artifactId\u003e\n        \u003cversion\u003e${aspectj.version}\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.testng\u003c/groupId\u003e\n        \u003cartifactId\u003etestng\u003c/artifactId\u003e\n        \u003cversion\u003e6.14.3\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eio.github.sskorol\u003c/groupId\u003e\n        \u003cartifactId\u003etest-data-supplier\u003c/artifactId\u003e\n        \u003cversion\u003e1.7.0\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n    \n\u003cbuild\u003e\n    \u003cplugins\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n            \u003cartifactId\u003emaven-compiler-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e${compiler.plugin.version}\u003c/version\u003e\n            \u003cconfiguration\u003e\n                \u003csource\u003e${java.version}\u003c/source\u003e\n                \u003ctarget\u003e${java.version}\u003c/target\u003e\n                \u003ccompilerArgs\u003e\n                    \u003carg\u003e-parameters\u003c/arg\u003e\n                \u003c/compilerArgs\u003e\n            \u003c/configuration\u003e\n        \u003c/plugin\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n            \u003cartifactId\u003emaven-surefire-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e${surefire.plugin.version}\u003c/version\u003e\n            \u003cconfiguration\u003e\n                \u003cargLine\u003e\n                    -javaagent:\"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar\"\n                \u003c/argLine\u003e\n            \u003c/configuration\u003e\n        \u003c/plugin\u003e\n    \u003c/plugins\u003e\n\u003c/build\u003e\n```\n\nCheck a separate [project](https://github.com/sskorol/test-data-supplier-maven-example) with usage examples.\n\n[**Go top**](#test-data-supplier) :point_up:\n\n### Gradle - Java 11-16 w/o modules\n\n```groovy\nplugins {\n    id 'java'\n}\n    \nsourceCompatibility = JavaVersion.VERSION_11\n    \nrepositories {\n    mavenCentral()\n}\n    \nconfigurations {\n    agent\n}\n\next {\n    aspectjVersion = '1.9.7'\n}\n\n[compileJava, compileTestJava]*.options*.compilerArgs = ['-parameters']\n    \ndependencies {\n    agent \"org.aspectj:aspectjweaver:${aspetjVersion}\"\n    implementation(\n            \"org.aspectj:aspectjweaver:${aspectjVersion}\",\n            'org.testng:testng:7.4.0',\n            'io.github.sskorol:test-data-supplier:1.9.7'\n    )\n}\n    \ntest {\n    doFirst {\n        jvmArgs(\"-javaagent:${configurations.agent.singleFile}\")\n    }\n    \n    useTestNG()\n}\n```\n\n[**Go top**](#test-data-supplier) :point_up:\n\n### Gradle - Java 11-16 w/ modules\n\nIt's a bit tricky in terms of building and testing modular applications:\n\n```groovy\nplugins {\n    id 'java-library'\n    id 'java'\n}\n    \next {\n    moduleName = 'your.module.name'\n}\n    \nsourceCompatibility = JavaVersion.VERSION_11\n    \nrepositories {\n    mavenCentral()\n}\n    \nconfigurations {\n    agent\n}\n\next {\n    aspectjVersion = '1.9.7'\n}\n    \ndependencies {\n    agent \"org.aspectj:aspectjweaver:${aspectjVersion}\"\n    implementation(\n            \"org.aspectj:aspectjweaver:${aspectjVersion}\",\n            'org.testng:testng:7.4.0',\n            'io.github.sskorol:test-data-supplier:1.9.7'\n    )\n}\n    \ncompileJava {\n    inputs.property(\"moduleName\", moduleName)\n    doFirst {\n        options.compilerArgs = [\n                '--module-path', classpath.asPath\n        ]\n        classpath = files()\n    }\n}\n   \ncompileTestJava {\n    inputs.property(\"moduleName\", moduleName)\n    doFirst {\n        options.compilerArgs = [\n                '--module-path', classpath.asPath,\n                '--patch-module', \"$moduleName=\" + files(sourceSets.test.java.srcDirs).asPath,\n        ]\n        classpath = files()\n    }\n}\n   \ntest {\n    useTestNG()\n   \n    inputs.property(\"moduleName\", moduleName)\n    doFirst {\n        jvmArgs = [\n                \"-javaagent:${configurations.agent.singleFile}\",\n                '--module-path', classpath.asPath,\n                '--add-modules', 'ALL-MODULE-PATH',\n                '--add-opens', 'your.module.name/test.package.path=org.testng',\n                '--add-opens', 'your.module.name/test.package.path=org.jooq.joor',\n                '--patch-module', \"$moduleName=\" + files(sourceSets.test.java.outputDir).asPath\n        ]\n        classpath = files()\n    }\n}\n```\n\nYour **module-info.java** may look like the following:\n\n```java\nmodule your.module.name {\n    requires io.github.sskorol.testdatasupplier;\n    requires org.testng;\n   \n    // Optional\n    provides io.github.sskorol.core.IAnnotationTransformerInterceptor\n        with path.to.transformer.ImplementationClass;\n   \n    provides io.github.sskorol.core.DataSupplierInterceptor\n        with path.to.interceptor.ImplementationClass;\n}\n```\n\n[**Go top**](#test-data-supplier) :point_up:\n\n### Gradle - Java 17+ w/o modules\n\nNote that `test-data-supplier:2.0.0+` has been compiled with java 17. It means you must use the same language level in your build file.\n\n```groovy\nplugins {\n    id 'java'\n}\n    \nsourceCompatibility = JavaVersion.VERSION_17\n    \nrepositories {\n    mavenCentral()\n}\n    \nconfigurations {\n    agent\n}\n\next {\n    aspectjVersion = '1.9.19'\n}\n\n[compileJava, compileTestJava]*.options*.compilerArgs = ['-parameters']\n    \ndependencies {\n    agent \"org.aspectj:aspectjweaver:${aspectjVersion}\"\n    implementation(\n            \"org.aspectj:aspectjweaver:${aspectjVersion}\",\n            'org.testng:testng:7.8.0',\n            'io.github.sskorol:test-data-supplier:2.3.0'\n    )\n}\n    \ntest {\n    doFirst {\n        jvmArgs(\n            \"-javaagent:${configurations.agent.singleFile}\",\n            '--add-opens', 'java.base/java.lang=ALL-UNNAMED'\n        )\n    }\n    \n    useTestNG()\n}\n```\n\n[**Go top**](#test-data-supplier) :point_up:\n\n### Maven - Java 17+ w/o modules\n\n```xml\n\u003cproperties\u003e\n    \u003caspectj.version\u003e1.9.19\u003c/aspectj.version\u003e\n    \u003cjava.version\u003e17\u003c/java.version\u003e\n    \u003ccompiler.plugin.version\u003e3.11.0\u003c/compiler.plugin.version\u003e\n    \u003csurefire.plugin.version\u003e3.0.0-M9\u003c/surefire.plugin.version\u003e\n\u003c/properties\u003e\n    \n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.aspectj\u003c/groupId\u003e\n        \u003cartifactId\u003easpectjweaver\u003c/artifactId\u003e\n        \u003cversion\u003e${aspectj.version}\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.testng\u003c/groupId\u003e\n        \u003cartifactId\u003etestng\u003c/artifactId\u003e\n        \u003cversion\u003e7.8.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eio.github.sskorol\u003c/groupId\u003e\n        \u003cartifactId\u003etest-data-supplier\u003c/artifactId\u003e\n        \u003cversion\u003e2.3.0\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n    \n\u003cbuild\u003e\n    \u003cplugins\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n            \u003cartifactId\u003emaven-compiler-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e${compiler.plugin.version}\u003c/version\u003e\n            \u003cconfiguration\u003e\n                \u003csource\u003e${java.version}\u003c/source\u003e\n                \u003ctarget\u003e${java.version}\u003c/target\u003e\n                \u003ccompilerArgs\u003e\n                    \u003carg\u003e-parameters\u003c/arg\u003e\n                \u003c/compilerArgs\u003e\n            \u003c/configuration\u003e\n        \u003c/plugin\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n            \u003cartifactId\u003emaven-surefire-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e${surefire.plugin.version}\u003c/version\u003e\n            \u003cconfiguration\u003e\n                \u003cargLine\u003e\n                    -javaagent:\"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar\"\n                \u003c/argLine\u003e\n            \u003c/configuration\u003e\n        \u003c/plugin\u003e\n    \u003c/plugins\u003e\n\u003c/build\u003e\n```\n\n[**Go top**](#test-data-supplier) :point_up:\n\n### API\n\nInstead of a common **DataProvider** annotation use the following:\n \n```java\n@DataSupplier\npublic T getData() {\n    //...\n}\n```\n\n**DataSupplier** supports the following args: **name**, **transpose**, **flatMap**, **runInParallel**, **indices** and **propagateTestFailure**. \n\nYou can refer **DataSupplier** the same way as with TestNG **DataProvider**:\n\n```java\n@Test(dataProvider = \"getData\")\npublic void supplyData(final T data) {\n    // ...\n}\n    \n// or\n    \n@Test(dataProviderClass = ExternalDataProvider.class, dataProvider = \"getData\")\npublic void supplyExternalData(final T data) {\n    // ...\n}\n```\n\nCheck **io.github.sskorol.testcases** package for more examples.\n\n[**Go top**](#test-data-supplier) :point_up:\n\n### JSON, CSV, YAML and XLSX processors\n\nTest data supplier supports JSON, CSV, YML and XLSX data retrieval. Assuming you have the following resources:\n\n```csv\nusername,password\n\"admin\",\"admin\"\n\"sskorol\",\"password\"\n\"guest\",\"123\"\n```\n\n```json\n[\n  {\n    \"username\": \"admin\",\n    \"password\": \"admin\"\n  },\n  {\n    \"username\": \"sskorol\",\n    \"password\": \"password\"\n  },\n  {\n    \"username\": \"guest\",\n    \"password\": \"123\"\n  }\n]\n```\n\n```yaml\n---\n username: admin\n password: admin\n---\n username: sskorol\n password: password\n---\n username: guest\n password: '123'\n```\n\n```xlsx\nUSERNAME  PASSWORD\nadmin     admin\nsskorol   password\nguest     123\n```\n\nYou can now map Java entities to these data sources using **@Source** annotation, which accepts either local file name \nor URL:\n\n```java\n@Data\n@Source(path = \"users.csv\")\npublic class User {\n    @FieldName(\"username\")\n    private final String name;\n    private final String password;\n}\n```\n\n```java\n@Data\n@Source(path = \"users.json\")\npublic class User {\n    @SerializedName(\"username\")\n    private final String name;\n    private final String password;\n}\n```\n\n```java\n@Data\n@NoArgsConstructor\n@Source(path = \"users.yml\")\npublic class User {\n    @JsonProperty(\"username\")\n    private final String name;\n    private final String password;\n}\n```\n\n```java\n@Data\n@NoArgsConstructor\n@Source(path = \"users.xlsx\")\n@Sheet(name = \"sheet_1\")\npublic class User {\n    @Column(name = \"USERNAME\")\n    private String username;\n\n    @Column(name = \"PASSWORD\")\n    private String password;\n}\n```\n\nIn case if some Java field's name differs from its data source representation, you can assign a valid name via \n**@FieldName** for CSV, **@SerializedName** for JSON and **@JsonProperty** for YML data type.\n\nExcel support is experimental. 2.0.0 version used [ZeroCell](https://github.com/creditdatamw/zerocell) library based on [Apache POI](https://github.com/apache/poi) to simplify corresponding files processing.\nSince 2.1.0, there's a custom implementation with similar approach, but minor improvements, e.g. there's no need to use column index anymore.\n\nIn terms of fields' mapping, you can use custom `@Column` annotation (don't confuse with ZeroCell Column).\nYou should also make sure you provided a sheet name via corresponding `@Sheet` annotation. Otherwise, the first one will be used.\nIn case if you have a similar structure on multiple sheets, you can use a repeatable `@Sheets` annotation.\nDynamic sheets' specification is also possible via `withAdditionalSources` builder method (see examples below).\n\nSimilarly to ZeroCell, you can use either default or custom fields' converters. Here's a list of defaults:\n\n- BooleanConverter\n- DoubleConverter\n- IntegerConverter\n- LocalDateConverter\n- LocalDateTimeConverter\n- StringConverter\n\nTo use custom converter, you should specify its class via `@Column` annotation.\n\n```java\n@Column(name = \"Tags\", converter = StringToListConverter.class)\nprivate List\u003cString\u003e data;\n```\n\nAnd the actual implementation may look like the following:\n\n```java\npublic class StringToListIConverter extends DefaultConverter\u003cList\u003cString\u003e\u003e {\n    @Override\n    public List\u003cString\u003e convert(final String value) {\n        return asList(value.split(\",\"));\n    }\n}\n```\n\nCustom converters must extend `DefaultConverter` class.\nAlso note that by default `test-data-supplier` uses an implicit conversion based on the field type.\nSo you don't have to explicitly specify a converter if it's among the defaults.\n\nLocal data sources must be located in a classpath. You usually use **resources** folder for that.\n\nThen, within `@DataSupplier` you can call a special **TestDataReader** builder to retrieve data from CSV, JSON, YML or XLSX data source. \nSee javadocs to get more details.\n\n```java\n@DataSupplier\npublic StreamEx\u003cUser\u003e getUsers() {\n    return use(CsvReader.class).withTarget(User.class).withSource(\"users.csv\").read();\n}\n```\n\n```java\n@DataSupplier\npublic StreamEx\u003cUser\u003e getUsers() {\n    return use(JsonReader.class).withTarget(User.class).withSource(\"http://users.json\").read();\n}\n```\n\n```java\n@DataSupplier\npublic StreamEx\u003cUser\u003e getUsers() {\n    return use(YamlReader.class).withTarget(User.class).read();\n}\n```\n\n```java\n@DataSupplier\npublic StreamEx\u003cUser\u003e getUsers() {\n    return use(XlsxReader.class).withTarget(User.class).read();\n}\n```\n\n```java\n@DataSupplier\npublic StreamEx\u003cUser\u003e getUsers() {\n    return use(XlsxReader.class).withTarget(User.class).withAdditionalSources(\"Sheet1\", \"Sheet2\").read();\n}\n```\n\nIf you want to specify a custom source in runtime, you can remove **@Source** annotation and use **withSource** builder \nmethod instead.\n`withAdditionalSources` builder method is experimental and implemented for `XlsxReader` as a dynamic sheets provider.\n\nNote that in case of a data reading error or any kind of exception thrown in a `@DataSupplier` body,\nthe corresponding test will be skipped. That's a default TestNG behaviour.\nHowever, you can set `propagateTestFailure` flag (introduced in TestNG 7.6.0) to explicitly mark the test as failed.\n\n[**Go top**](#test-data-supplier) :point_up:\n\n### DB support\n\nTechnically, there's no need to create an additional ORM wrapper to work with databases. But it's worth to show how to perform such integration.\n\nLet's use [ebean](https://ebean.io/docs/getting-started/) and Postgres as an example.\n\nFirst, create an `application-test.yaml` with db connection details in your test resources' folder:\n```yaml\nebean:\n  test:\n    useDocker: false\n    platform: postgres\n    ddlMode: none\n    dbName: your_db\n    dbSchema: your_schema\n    postgres:\n      username: your_username\n      password: your_password\n      url: jdbc:postgresql://localhost:5432/your_db\n```\n\nNext, create a mapping with your DB table:\n```java\n@MappedSuperclass\npublic class BaseEntity extends Model {\n    @Id\n    long id;\n}\n\n@Entity\n@Table(name = \"testing.users\")\npublic class UserEntity extends BaseEntity {\n    @NotNull\n    public String email;\n\n    @Column(name = \"is_active\")\n    public boolean isActive;\n}\n```\n\nNow, you can supply users to your test the following way:\n```java\n@DataSupplier\npublic List\u003cUserEntity\u003e usersData() {\n    return find(UserEntity.class)\n        .where()\n        .like(\"email\", \"%korol%@gmail.com\")\n        .and()\n        .eq(\"is_active\", true)\n        .findList();\n}\n```\n\n[**Go top**](#test-data-supplier) :point_up:\n\n### Factory\n\nYou can specify **DataSupplier** for **Factory** annotation as well as for common test methods.\n\n```java\n@NoArgsConstructor\npublic class InternalFactoryTests {\n    \n    @DataSupplier\n    public StreamEx getConstructorData() {\n        return IntStreamEx.rangeClosed(1, 3).boxed();\n    }\n    \n    @DataSupplier\n    public String getTestData() {\n        return \"data\";\n    }\n    \n    @Factory(dataProvider = \"getConstructorData\", dataProviderClass = InternalFactoryTests.class)\n    public InternalFactoryTests(final int index) {\n        // not implemented\n    }\n    \n    @Test(dataProvider = \"getTestData\")\n    public void internalFactoryTest(final String data) {\n        // not implemented\n    }\n}\n```\n\n[**Go top**](#test-data-supplier) :point_up:\n\n### Tracking meta-data\n\n**DataSupplierInterceptor** interface allows tracking original **DataProvider** method calls for accessing additional meta-data. You can use the following snippet for getting required info:\n```java\npublic class DataSupplierInterceptorImpl implements DataSupplierInterceptor {\n    \n    private static final Map\u003cITestNGMethod, DataSupplierMetaData\u003e META_DATA = new ConcurrentHashMap\u003c\u003e();\n    \n    @Override\n    public void beforeDataPreparation(final ITestContext context, final ITestNGMethod method) {\n    }\n    \n    @Override\n    public void afterDataPreparation(final ITestContext context, final ITestNGMethod method) {\n    }\n    \n    @Override\n    public void onDataPreparation(final DataSupplierMetaData testMetaData) {\n        META_DATA.putIfAbsent(testMetaData.getTestMethod(), testMetaData);\n    }\n    \n    @Override\n    public Collection\u003cDataSupplierMetaData\u003e getMetaData() {\n        return META_DATA.values();\n    }\n}\n```\n\nThis class should be then loaded via SPI mechanism. Just create **META-INF/services** folder in **resources** root, and add a new file **io.github.sskorol.core.DataSupplierInterceptor** with a full path to implementation class.\n\n[**Go top**](#test-data-supplier) :point_up:\n\n### IAnnotationTransformer restriction\n\nTestNG restricts users in a number of **IAnnotationTransformer** implementations. You may have not more than a single transformer within project's scope.\nAs **test-data-supplier** uses this interface for its internal stuff, you won't be able to apply your own implementation.\n\nIn case if you still need to add a custom **IAnnotationTransformer**, you have to implement the following interface: \n\n```java\npublic class IAnnotationTransformerInterceptorImpl implements IAnnotationTransformerInterceptor {\n\n    @Override\n    public void transform(IFactoryAnnotation annotation, Method testMethod) {\n    }\n\n    @Override\n    public void transform(IConfigurationAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {\n    }\n\n    @Override\n    public void transform(IDataProviderAnnotation annotation, Method method) {\n    }\n\n    @Override\n    public void transform(IListenersAnnotation annotation, Class testClass) {\n    }\n}\n```\n\nIt's just an SPI wrapper for common TestNG feature. Use the same technique as for **DataSupplierInterceptor** to include it into your project.\n\nNote that in case if you want to manage **DataProviderTransformer** manually, you have to use a special spi-off distribution:\n\n```groovy\ndependencies {\n    implementation 'io.github.sskorol:test-data-supplier:2.3.0:spi-off'\n}\n```\n\n[**Go top**](#test-data-supplier) :point_up:\n\n## IntelliJ IDEA support\n\n**Test Data Supplier** also has an IntelliJ IDEA plugin. Just install **test-data-supplier-plugin** from the official JetBrains repository.\n\nMore information about its features can be found on the related [GitHub](https://github.com/sskorol/test-data-supplier-plugin) page.\n\n[**Go top**](#test-data-supplier) :point_up:\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsskorol%2Ftest-data-supplier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsskorol%2Ftest-data-supplier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsskorol%2Ftest-data-supplier/lists"}