diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index d75b26e..972c3a4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -30,20 +30,19 @@ ToDo ### Environment -| Component | Version | -|---------------------|-------------------| -| Test Data Supplier | 2.2.0 | -| TestNG | 7.7.1 | -| Build tool | gradle@7.6.0 | -| IDE | IntelliJ@2022.2.3 | -| JDK | temurin-17.0.6 | +| Component | Version | +|---------------------|-----------------| +| Test Data Supplier | 2.2.0 | +| TestNG | 7.8.0 | +| Build tool | gradle@8.2.1 | +| IDE | IntelliJ@2023.2 | +| JDK | temurin-17.0.8 | ### Can be reproduced via - [ ] Bash - [ ] Maven - [ ] Gradle -- [ ] Eclipse - [ ] IntelliJ ### Expected behavior diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index a86c284..ebaa6fa 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -30,20 +30,19 @@ ToDo ### Environment -| Component | Version | -|--------------------|-------------------| -| Test Data Supplier | 2.2.0 | -| TestNG | 7.7.1 | -| Build tool | gradle@7.6.0 | -| IDE | IntelliJ@2022.2.3 | -| JDK | temurin-17.0.6 | +| Component | Version | +|--------------------|-----------------| +| Test Data Supplier | 2.2.0 | +| TestNG | 7.8.0 | +| Build tool | gradle@8.2.1 | +| IDE | IntelliJ@2023.2 | +| JDK | temurin-17.0.8 | ### Can be reproduced via - [ ] Bash - [ ] Maven - [ ] Gradle -- [ ] Eclipse - [ ] IntelliJ ### Expected behavior diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 934a2f7..951e7f7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -9,3 +9,5 @@ Closes # ### Checklist - [ ] Added unit / integration tests - [ ] Added documentation +- [ ] Updated configuration +- [ ] None of the above is required diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c568e28..c74bbe9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,6 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} run: ./gradlew clean sonar - - name: Built and Test on Depenabot PR + - name: Built and Test on Dependabot PR if: ${{ github.actor == 'dependabot[bot]' }} run: ./gradlew clean test diff --git a/README.md b/README.md index 0249b3e..83db2e2 100644 --- a/README.md +++ b/README.md @@ -416,8 +416,8 @@ dependencies { agent "org.aspectj:aspectjweaver:${aspectjVersion}" implementation( "org.aspectj:aspectjweaver:${aspectjVersion}", - 'org.testng:testng:7.7.1', - 'io.github.sskorol:test-data-supplier:2.2.0' + 'org.testng:testng:7.8.0', + 'io.github.sskorol:test-data-supplier:2.3.0' ) } @@ -454,12 +454,12 @@ test { org.testng testng - 7.7.1 + 7.8.0 io.github.sskorol test-data-supplier - 2.2.0 + 2.3.0 @@ -629,6 +629,8 @@ Since 2.1.0, there's a custom implementation with similar approach, but minor im In terms of fields' mapping, you can use custom `@Column` annotation (don't confuse with ZeroCell Column). You should also make sure you provided a sheet name via corresponding `@Sheet` annotation. Otherwise, the first one will be used. +In case if you have a similar structure on multiple sheets, you can use a repeatable `@Sheets` annotation. +Dynamic sheets' specification is also possible via `withAdditionalSources` builder method (see examples below). Similarly to ZeroCell, you can use either default or custom fields' converters. Here's a list of defaults: @@ -694,8 +696,16 @@ public StreamEx getUsers() { } ``` +```java +@DataSupplier +public StreamEx getUsers() { + return use(XlsxReader.class).withTarget(User.class).withAdditionalSources("Sheet1", "Sheet2").read(); +} +``` + If you want to specify a custom source in runtime, you can remove **@Source** annotation and use **withSource** builder method instead. +`withAdditionalSources` builder method is experimental and implemented for `XlsxReader` as a dynamic sheets provider. Note that in case of a data reading error or any kind of exception thrown in a `@DataSupplier` body, the corresponding test will be skipped. That's a default TestNG behaviour. @@ -856,7 +866,7 @@ Note that in case if you want to manage **DataProviderTransformer** manually, yo ```groovy dependencies { - implementation 'io.github.sskorol:test-data-supplier:2.2.0:spi-off' + implementation 'io.github.sskorol:test-data-supplier:2.3.0:spi-off' } ``` diff --git a/build.gradle.kts b/build.gradle.kts index a7a05d2..02de8fc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { jacoco `maven-publish` signing - id("io.github.gradle-nexus.publish-plugin") version "1.3.0" + id("io.github.gradle-nexus.publish-plugin") version "2.0.0-rc-1" id("org.sonarqube") version "4.3.0.3225" id("net.researchgate.release") version "3.0.2" id("com.github.ben-manes.versions") version "0.47.0" @@ -22,9 +22,21 @@ val projectUrl by extra("https://github.com/sskorol/test-data-supplier") val moduleName by extra("io.github.sskorol.testdatasupplier") val aspectjVersion by extra("1.9.19") -val jacksonVersion by extra("2.14.2") -val lombokVersion by extra("1.18.26") +val jacksonVersion by extra("2.15.2") +val lombokVersion by extra("1.18.28") val poiVersion by extra("5.2.3") +val joorVersion by extra ("0.9.14") +val testngVersion by extra("7.8.0") +val streamexVersion by extra("0.8.1") +// Don't update to the latest, as it's outdated +val vavrVersion by extra("0.10.4") +val reflectionsVersion by extra("0.10.2") +val commonsCsvVersion by extra("1.10.0") +val gsonVersion by extra("2.10.1") +val assertjVersion by extra("3.24.2") +val logbackVersion by extra("1.4.8") +val log4jVersion by extra("2.20.0") +val mockitoVersion by extra("5.4.0") val agent: Configuration by configurations.creating @@ -63,24 +75,24 @@ dependencies { testCompileOnly("org.projectlombok:lombok:${lombokVersion}") annotationProcessor("org.projectlombok:lombok:${lombokVersion}") testAnnotationProcessor("org.projectlombok:lombok:${lombokVersion}") - api("org.jooq:joor:0.9.14") - api("org.testng:testng:7.8.0") - api("one.util:streamex:0.8.1") - api("io.vavr:vavr:0.10.4") + api("org.jooq:joor:${joorVersion}") + api("org.testng:testng:${testngVersion}") + api("one.util:streamex:${streamexVersion}") + api("io.vavr:vavr:${vavrVersion}") api("org.aspectj:aspectjrt:${aspectjVersion}") - api("org.reflections:reflections:0.10.2") - api("org.apache.commons:commons-csv:1.10.0") - api("com.google.code.gson:gson:2.10.1") + api("org.reflections:reflections:${reflectionsVersion}") + api("org.apache.commons:commons-csv:${commonsCsvVersion}") + api("com.google.code.gson:gson:${gsonVersion}") api("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${jacksonVersion}") api("com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}") api("org.apache.poi:poi:${poiVersion}") api("org.apache.poi:poi-ooxml:${poiVersion}") - api("org.assertj:assertj-core:3.24.2") + api("org.assertj:assertj-core:${assertjVersion}") // Transitive dependency: <=1.33 version has vulnerabilities. Remove when updated by top-level packages. api("org.yaml:snakeyaml:2.0") - testImplementation("ch.qos.logback:logback-classic:1.4.8") - testImplementation("org.apache.logging.log4j:log4j-core:2.20.0") - testImplementation("org.mockito:mockito-core:5.4.0") + testImplementation("ch.qos.logback:logback-classic:${logbackVersion}") + testImplementation("org.apache.logging.log4j:log4j-core:${log4jVersion}") + testImplementation("org.mockito:mockito-core:${mockitoVersion}") } jacoco.toolVersion = "0.8.8" @@ -128,7 +140,7 @@ tasks.withType { } tasks.withType(Wrapper::class) { - gradleVersion = "8.0.1" + gradleVersion = "8.2.1" } tasks.compileJava { @@ -231,7 +243,7 @@ publishing { developers { developer { id.set("sskorol") - name.set("Sergey Korol") + name.set("Serhii Korol") email.set("serhii.s.korol@gmail.com") } } @@ -250,7 +262,7 @@ publishing { } nexusPublishing { - repositories { + this.repositories { sonatype { val osshUsername = System.getenv("OSSH_USERNAME") ?: "" val osshPassword = System.getenv("OSSH_PASSWORD") ?: "" @@ -295,6 +307,8 @@ tasks.jar { } tasks.register("sourceJar") { + group = "sourceJar" + description = "Build a jar from sources" dependsOn(tasks.classes) inputs.property("moduleName", moduleName) manifest { @@ -315,6 +329,8 @@ tasks.register("sourceJar") { } tasks.register("spiOffJar") { + group = "spiOffJar" + description = "Build a jar from sources excluding SPI" dependsOn(tasks.classes) inputs.property("moduleName", moduleName) manifest { diff --git a/gradle.properties b/gradle.properties index d798659..c2677ba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=2.2.1 +version=2.3.0 systemProp.sonar.host.url=https://sonarcloud.io systemProp.sonar.projectKey=io.github.sskorol:test-data-supplier systemProp.sonar.organization=sskorol-github diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f72df95..84a0b92 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/io/github/sskorol/data/DataReader.java b/src/main/java/io/github/sskorol/data/DataReader.java index e88d860..0c12231 100644 --- a/src/main/java/io/github/sskorol/data/DataReader.java +++ b/src/main/java/io/github/sskorol/data/DataReader.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.net.URL; +import java.util.List; import static io.github.sskorol.utils.ReflectionUtils.getSourcePath; @@ -15,6 +16,10 @@ public interface DataReader { String getPath(); + default DataReader additionalSources(final List names) { + return this; + } + default URL getUrl() throws IOException { return getPath().isEmpty() ? getSourcePath(getEntityClass()) : getSourcePath(getPath()); } diff --git a/src/main/java/io/github/sskorol/data/Sheet.java b/src/main/java/io/github/sskorol/data/Sheet.java index 65d4f7f..e36c139 100644 --- a/src/main/java/io/github/sskorol/data/Sheet.java +++ b/src/main/java/io/github/sskorol/data/Sheet.java @@ -1,13 +1,11 @@ package io.github.sskorol.data; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import java.lang.annotation.*; /** * Use this annotation to provide Excel sheet name. If none is specified hte first one is used. */ +@Repeatable(Sheets.class) @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Sheet { diff --git a/src/main/java/io/github/sskorol/data/Sheets.java b/src/main/java/io/github/sskorol/data/Sheets.java new file mode 100644 index 0000000..e551228 --- /dev/null +++ b/src/main/java/io/github/sskorol/data/Sheets.java @@ -0,0 +1,12 @@ +package io.github.sskorol.data; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Sheets { + Sheet[] value(); +} diff --git a/src/main/java/io/github/sskorol/data/TestDataReader.java b/src/main/java/io/github/sskorol/data/TestDataReader.java index c0eed39..5c9acc0 100644 --- a/src/main/java/io/github/sskorol/data/TestDataReader.java +++ b/src/main/java/io/github/sskorol/data/TestDataReader.java @@ -3,6 +3,8 @@ import lombok.AllArgsConstructor; import one.util.streamex.StreamEx; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import static org.joor.Reflect.onClass; @@ -37,11 +39,13 @@ public static class DataBuilder { private final Class dataReaderClass; private final Class entityClass; + private final List additionalSources; private String path; public DataBuilder(final Class dataReaderClass, final Class entityClass) { this.dataReaderClass = dataReaderClass; this.entityClass = entityClass; + this.additionalSources = new ArrayList<>(); } public DataBuilder withSource(final String path) { @@ -49,9 +53,18 @@ public DataBuilder withSource(final String path) { return this; } + public DataBuilder withAdditionalSources(final String... names) { + this.additionalSources.addAll(List.of(names)); + return this; + } + public StreamEx read() { var args = StreamEx.of(entityClass, path).filter(Objects::nonNull).toArray(); - return onClass(dataReaderClass).create(args).call("read").get(); + return onClass(dataReaderClass) + .create(args) + .call("additionalSources", additionalSources) + .call("read") + .get(); } } } diff --git a/src/main/java/io/github/sskorol/data/XlsxCellMapper.java b/src/main/java/io/github/sskorol/data/XlsxCellMapper.java index 01316ef..c4f42a4 100644 --- a/src/main/java/io/github/sskorol/data/XlsxCellMapper.java +++ b/src/main/java/io/github/sskorol/data/XlsxCellMapper.java @@ -73,10 +73,12 @@ private IConverter findMatchingConverter() { .map(Column::converter) .map(converterClass -> (IConverter) onClass(converterClass).create().get()) .filter(converterInstance -> converterInstance.getType().equals(getFieldType())) - .orElseGet(() -> StreamEx.of(defaultIConverters) + .orElseGet(() -> StreamEx + .of(defaultIConverters) .findFirst(converterInstance -> converterInstance.getType().equals(getFieldType())) .orElseThrow(() -> new IllegalStateException(format( - "There's no matching converter found for %s field of type %s", getFieldName(), getFieldType())) + "There's no matching converter found for %s field of type %s", + getFieldName(), getFieldType())) ) ); } diff --git a/src/main/java/io/github/sskorol/data/XlsxReader.java b/src/main/java/io/github/sskorol/data/XlsxReader.java index dec8d3c..6accb9f 100644 --- a/src/main/java/io/github/sskorol/data/XlsxReader.java +++ b/src/main/java/io/github/sskorol/data/XlsxReader.java @@ -1,14 +1,17 @@ package io.github.sskorol.data; import io.github.sskorol.converters.*; +import io.vavr.Tuple; import lombok.Getter; +import one.util.streamex.IntStreamEx; import one.util.streamex.StreamEx; import org.apache.poi.ss.usermodel.*; import java.util.*; +import java.util.function.Function; import static java.lang.String.format; -import static java.util.Optional.ofNullable; +import static org.apache.poi.ss.usermodel.CellType.BLANK; import static org.joor.Reflect.onClass; public class XlsxReader implements DataReader { @@ -18,11 +21,13 @@ public class XlsxReader implements DataReader { @Getter private final String path; private final List> defaultIConverters; + private final List sheetNames; public XlsxReader(final Class entityClass, final String path) { this.entityClass = entityClass; this.path = path; this.defaultIConverters = defaultConverters(); + this.sheetNames = new ArrayList<>(); } public XlsxReader(final Class entityClass) { @@ -31,7 +36,8 @@ public XlsxReader(final Class entityClass) { @SuppressWarnings("unchecked") public static List> defaultConverters() { - return StreamEx.of( + return StreamEx + .of( BooleanConverter.class, StringConverter.class, IntegerConverter.class, @@ -49,21 +55,23 @@ public StreamEx read() { var startIndex = 0; var skip = 1; - var sheet = ofNullable(entityClass.getDeclaredAnnotation(Sheet.class)) - .map(annotation -> workbook.getSheet(annotation.name())) - .orElse(workbook.getSheetAt(startIndex)); - - var headers = StreamEx.of(sheet.getRow(startIndex).cellIterator()) - .toMap(cell -> formatter.formatCellValue(cell).trim(), Cell::getColumnIndex); - - var cellMappers = StreamEx.of(entityClass.getDeclaredFields()) - .map(field -> new XlsxCellMapper<>(field, headers, defaultIConverters)) - .toList(); - - return StreamEx.of(sheet.iterator()) - .skip(skip) - .map(row -> StreamEx.of(cellMappers).map(cellMapper -> cellMapper.parse(row)).toList()) - .map(this::initEntity); + var sheets = getSheetNames() + .map(workbook::getSheet) + .toMutableList(); + + if (sheets.isEmpty()) { + sheets.add(workbook.getSheetAt(startIndex)); + } + + return StreamEx + .of(sheets) + .flatMap(sheet -> StreamEx + .of(sheet.iterator()) + .skip(skip) + .filter(row -> !isRowEmpty(row)) + .map(mappersOf(sheet, startIndex, formatter)) + .map(this::initEntity) + ); } catch (Exception ex) { throw new IllegalArgumentException(format("Unable to read XLSX data to %s.", entityClass), ex); } @@ -71,8 +79,10 @@ public StreamEx read() { @SuppressWarnings("unchecked") public T initEntity(final List> mappers) { - var hasDefaultConstructor = StreamEx.of(entityClass.getDeclaredConstructors()) + var hasDefaultConstructor = StreamEx + .of(entityClass.getDeclaredConstructors()) .anyMatch(constructor -> constructor.getParameterCount() == 0); + if (!hasDefaultConstructor) { throw new IllegalStateException(format("%s must have default constructor.", entityClass.getSimpleName())); } @@ -82,4 +92,43 @@ public T initEntity(final List> mappers) { return entity; } + + @Override + public XlsxReader additionalSources(final List names) { + this.sheetNames.addAll(names); + return this; + } + + private Function>> mappersOf( + final org.apache.poi.ss.usermodel.Sheet sheet, + final int startIndex, + final DataFormatter formatter + ) { + var headers = StreamEx + .of(sheet.getRow(startIndex).cellIterator()) + .map(cell -> Tuple.of(cell, formatter.formatCellValue(cell).trim())) + .filter(cell -> !cell._2.isEmpty()) + .toMap(cell -> cell._2, pair -> pair._1.getColumnIndex()); + + return row -> StreamEx + .of(entityClass.getDeclaredFields()) + .map(field -> new XlsxCellMapper<>(field, headers, defaultIConverters)) + .map(cellMapper -> cellMapper.parse(row)) + .toList(); + } + + private boolean isRowEmpty(final Row row) { + return row == null || row.getLastCellNum() <= 0 || + IntStreamEx + .range(row.getFirstCellNum(), row.getLastCellNum()) + .mapToObj(row::getCell) + .filter(Objects::nonNull) + .noneMatch(cell -> cell.getCellType() != BLANK && !cell.toString().isEmpty()); + } + + private StreamEx getSheetNames() { + return !sheetNames.isEmpty() ? + StreamEx.of(sheetNames) : + StreamEx.of(entityClass.getAnnotationsByType(Sheet.class)).map(Sheet::name); + } } diff --git a/src/test/java/io/github/sskorol/datasuppliers/ExternalDataSuppliers.java b/src/test/java/io/github/sskorol/datasuppliers/ExternalDataSuppliers.java index 527d369..fe392e1 100644 --- a/src/test/java/io/github/sskorol/datasuppliers/ExternalDataSuppliers.java +++ b/src/test/java/io/github/sskorol/datasuppliers/ExternalDataSuppliers.java @@ -18,8 +18,8 @@ public class ExternalDataSuppliers { @DataSupplier(transpose = true) public User[] getExternalArrayData() { return new User[]{ - new User("user1", "password1"), - new User("user2", "password2") + new User("user1", "password1"), + new User("user2", "password2") }; } @@ -30,9 +30,10 @@ public List getExternalCollectionData() { @DataSupplier public Stream getExternalStreamData() { - return LongStream.range(0, 10) - .filter(i -> i % 2 != 0) - .boxed(); + return LongStream + .range(0, 10) + .filter(i -> i % 2 != 0) + .boxed(); } @DataSupplier diff --git a/src/test/java/io/github/sskorol/entities/XlsxData.java b/src/test/java/io/github/sskorol/entities/XlsxData.java index 23824a2..5079a10 100644 --- a/src/test/java/io/github/sskorol/entities/XlsxData.java +++ b/src/test/java/io/github/sskorol/entities/XlsxData.java @@ -4,6 +4,7 @@ import io.github.sskorol.converters.StringToListIConverter; import io.github.sskorol.data.Column; import io.github.sskorol.data.Sheet; +import io.github.sskorol.data.Sheets; import io.github.sskorol.data.Source; import lombok.Data; @@ -13,7 +14,10 @@ @Data @Source(path = "random.xlsx") -@Sheet(name = "Sheet1") +@Sheets(value = { + @Sheet(name = "Sheet1"), + @Sheet(name = "Sheet2") +}) public class XlsxData { @Column(name = "TC") diff --git a/src/test/java/io/github/sskorol/testcases/DataSupplierTests.java b/src/test/java/io/github/sskorol/testcases/DataSupplierTests.java index d37d2b7..1e77094 100644 --- a/src/test/java/io/github/sskorol/testcases/DataSupplierTests.java +++ b/src/test/java/io/github/sskorol/testcases/DataSupplierTests.java @@ -388,8 +388,8 @@ public void ymlDataSupplierTestsShouldWork() { public void xlsxDataSupplierTestsShouldWork() { var listener = run(XlsxDataSupplierTests.class); assertThat(listener.getSucceedMethodNames()) - .hasSize(15) - .contains( + .hasSize(27) + .containsExactlyInAnyOrder( "shouldReadLocalExcelSpreadsheetWithoutSheet(PersonWithoutSheet(firstName=Zikani, " + "lastName=Nyirenda, dateOfBirth=1993-04-03))", "shouldReadLocalExcelSpreadsheetWithoutSheet(PersonWithoutSheet(firstName=Andrew, " + @@ -410,8 +410,6 @@ public void xlsxDataSupplierTestsShouldWork() { "lastName=Chikhula, dateOfBirth=1986-04-05))", "shouldReadLocalExcelSpreadsheetWithSheet(PersonWithSheet(firstName=Moses, lastName=Mpulula, " + "dateOfBirth=1992-01-10))", - "shouldReadLocalExcelSpreadsheetWithSheet(PersonWithSheet(firstName=Moses, lastName=Mpulula, " + - "dateOfBirth=1992-01-10))", "shouldReadLocalExcelSpreadsheetWithCustomConverters(XlsxData(testCase=test1, browser=chrome, " + "date=2022-05-19, nextCheck=2022-06-11T10:22:33, price=0.22, shouldRun=true, age=20, " + "phoneNumber=+919876543210, techStack=[selenium, appium, restassured]))", @@ -426,7 +424,43 @@ public void xlsxDataSupplierTestsShouldWork() { "phoneNumber=+919876543210, techStack=[automation, performance, security]))", "shouldReadLocalExcelSpreadsheetWithCustomConverters(XlsxData(testCase=test5, browser=chromium, " + "date=2022-02-28, nextCheck=2022-04-04T12:22:33, price=1000.0, shouldRun=true, age=101, " + - "phoneNumber=+918291239893, techStack=[allure, testng, java, gradle]))" + "phoneNumber=+918291239893, techStack=[allure, testng, java, gradle]))", + "shouldReadLocalExcelSpreadsheetWithCustomConverters(XlsxData(testCase=test6, browser=firefox, " + + "date=2022-05-19, nextCheck=2022-06-11T10:22:33, price=0.22, shouldRun=true, age=20, " + + "phoneNumber=+919876543210, techStack=[selenium, appium, restassured]))", + "shouldReadLocalExcelSpreadsheetWithCustomConverters(XlsxData(testCase=test7, browser=chrome, " + + "date=2022-04-09, nextCheck=2022-05-21T11:02:13, price=3.55, shouldRun=false, age=23, " + + "phoneNumber=+919876543210, techStack=[docker, k8s, openshift]))", + "shouldReadLocalExcelSpreadsheetWithCustomConverters(XlsxData(testCase=test8, browser=firefox, " + + "date=2021-08-12, nextCheck=2023-02-01T00:00, price=0.0, shouldRun=true, age=21, " + + "phoneNumber=+919876543210, techStack=[postman, soapui]))", + "shouldReadLocalExcelSpreadsheetWithCustomConverters(XlsxData(testCase=test9, browser=edge, " + + "date=2023-01-01, nextCheck=2022-12-11T11:32:32, price=-1.24, shouldRun=true, age=22, " + + "phoneNumber=+919876543210, techStack=[automation, performance, security]))", + "shouldReadLocalExcelSpreadsheetWithCustomConverters(XlsxData(testCase=test10, browser=firefox, " + + "date=2022-02-28, nextCheck=2022-04-04T12:22:33, price=1000.0, shouldRun=true, age=101, " + + "phoneNumber=+918291239893, techStack=[allure, testng, java, gradle]))", + "shouldReadLocalExcelSpreadsheetWithCustomSheets(XlsxData(testCase=test6, browser=firefox, " + + "date=2022-05-19, nextCheck=2022-06-11T10:22:33, price=0.22, shouldRun=true, age=20, " + + "phoneNumber=+919876543210, techStack=[selenium, appium, restassured]))", + "shouldReadLocalExcelSpreadsheetWithCustomSheets(XlsxData(testCase=test7, browser=chrome, " + + "date=2022-04-09, nextCheck=2022-05-21T11:02:13, price=3.55, shouldRun=false, age=23, " + + "phoneNumber=+919876543210, techStack=[docker, k8s, openshift]))", + "shouldReadLocalExcelSpreadsheetWithCustomSheets(XlsxData(testCase=test8, browser=firefox, " + + "date=2021-08-12, nextCheck=2023-02-01T00:00, price=0.0, shouldRun=true, age=21, " + + "phoneNumber=+919876543210, techStack=[postman, soapui]))", + "shouldReadLocalExcelSpreadsheetWithCustomSheets(XlsxData(testCase=test9, browser=edge, " + + "date=2023-01-01, nextCheck=2022-12-11T11:32:32, price=-1.24, shouldRun=true, age=22, " + + "phoneNumber=+919876543210, techStack=[automation, performance, security]))", + "shouldReadLocalExcelSpreadsheetWithCustomSheets(XlsxData(testCase=test10, browser=firefox, " + + "date=2022-02-28, nextCheck=2022-04-04T12:22:33, price=1000.0, shouldRun=true, age=101, " + + "phoneNumber=+918291239893, techStack=[allure, testng, java, gradle]))", + "shouldReadLocalExcelSpreadsheetWithCustomSheets(XlsxData(testCase=test11, browser=edge, " + + "date=2022-05-19, nextCheck=2022-06-11T10:22:33, price=0.24, shouldRun=true, age=20, " + + "phoneNumber=+919876543210, techStack=[selenium, appium, restassured]))", + "shouldReadLocalExcelSpreadsheetWithCustomSheets(XlsxData(testCase=test12, browser=firefox, " + + "date=2022-04-09, nextCheck=2022-05-21T11:02:13, price=2.12, shouldRun=false, age=23, " + + "phoneNumber=+919876543210, techStack=[docker, k8s, openshift]))" ); assertThat(listener.getSkippedBeforeInvocationMethodNames()) diff --git a/src/test/java/io/github/sskorol/testcases/XlsxDataSupplierTests.java b/src/test/java/io/github/sskorol/testcases/XlsxDataSupplierTests.java index 8bb0929..a81c2ea 100644 --- a/src/test/java/io/github/sskorol/testcases/XlsxDataSupplierTests.java +++ b/src/test/java/io/github/sskorol/testcases/XlsxDataSupplierTests.java @@ -30,6 +30,14 @@ public StreamEx getDataWithCustomConverters() { return use(XlsxReader.class).withTarget(XlsxData.class).read(); } + @DataSupplier(propagateTestFailure = true) + public StreamEx getDataWithCustomSheets() { + return use(XlsxReader.class) + .withTarget(XlsxData.class) + .withAdditionalSources("Sheet2", "Sheet3") + .read(); + } + @Test(dataProvider = "getPersonsWithoutSheet") public void shouldReadLocalExcelSpreadsheetWithoutSheet(final PersonWithoutSheet person) { // not implemented @@ -49,4 +57,9 @@ public void shouldNotBeExecutedWithMissingXlsxResource(final MissingClient missi public void shouldReadLocalExcelSpreadsheetWithCustomConverters(final XlsxData xlsxData) { // not implemented } + + @Test(dataProvider = "getDataWithCustomSheets") + public void shouldReadLocalExcelSpreadsheetWithCustomSheets(final XlsxData xlsxData) { + // not implemented + } } diff --git a/src/test/resources/random.xlsx b/src/test/resources/random.xlsx index 8ea138d..4fb74c5 100644 Binary files a/src/test/resources/random.xlsx and b/src/test/resources/random.xlsx differ