Nested @dataprovider?

classic Classic list List threaded Threaded
2 messages Options
BN
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Nested @dataprovider?

BN
Here is a situation I have and any ideas/suggestions will be great.

For example: lets say I have a file for eg. country.csv with many countries, 
usa
canada
japan

then for each of these countries, I have files like 
usa_states.csv
usa_weather.csv
usa_geography.csv

canada_states.csv
canada_weather.csv
canada_geography.csv

japan_states.csv
japan_weather.csv
japan_geography.csv

All these files have very similar data (in terms of the fields/columns) and I perform the exact same test on each of this file. So I will have 9 @test methods one for each file. I have 1 @dataprovider and feed the filename from each @test 

In the real situation, this can multiply and get pretty big.
Is there anyway, I can reduce this? I looked at the solution of combining 2 dataprovider methods, but that doesn't help because, I'm not trying to combine the 2 files
I need one value to be picked from my first csv file and then run the test for each value in the second one and the second dataprovider will be providing me with all the rows & columns of the individual files.

In a way, I think I'm looking for a nested dataprovider functionality.


--
You received this message because you are subscribed to the Google Groups "testng-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/testng-users.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Nested @dataprovider?

Krishnan Mahadevan
Maybe you can use something like this ?

english.csv
Rama (Amar Chitra Katha),70,Anant Pai
Moin the Monster Songster,124,Anushka Ravishankar and Anitha Balachandran
5 Minute Bedtime Stories,151,NA
hindi.csv
Ashad ka Ek Din, 102,Mohan Rakesh
Tenali Ram,75, Ganga Parasad Sharma
Harry Potter Aur Paras Patthar,116,J.K. Rowling
CsvReader.java

package com.rationaleemotions.googleforums.nested;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;

/**
 * Code borrowed from http://www.java67.com/2015/08/how-to-load-data-from-csv-file-in-java.html
 */
public class CsvReader {
    private String fileName;

    public CsvReader(String fileName) {
        this.fileName = fileName;
    }

    public Book[] getBooks() throws IOException {
        List<Book> books = new LinkedList<>();
        Path pathToFile = Paths.get(fileName);
        try (BufferedReader br = Files.newBufferedReader(pathToFile, StandardCharsets.UTF_8)) {
            String line = br.readLine();
            while (line != null) {
                String[] attributes = line.split(",");
                Book book = Book.createBook(attributes);
                books.add(book);
                line = br.readLine();
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }

        return books.toArray(new Book[books.size()]);
    }

    public static class Book {
        private String name;
        private int price;
        private String author;

        public static Book createBook(String[] metadata) {
            String name = metadata[0];
            int price = Integer.parseInt(metadata[1].trim());
            String author = metadata[2];
            return new Book(name, price, author);
        }

        private Book(String name, int price, String author) {
            this.name = name;
            this.price = price;
            this.author = author;
        }

        public String getName() {
            return name;
        }

        public int getPrice() {
            return price;
        }

        public String getAuthor() {
            return author;
        }

        @Override
        public String toString() {
            return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", author='" + author + '\'' +
                '}';
        }
    }
}
BookTest.java

package com.rationaleemotions.googleforums.nested;

import org.testng.Assert;
import org.testng.ITestContext;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Factory;
import org.testng.annotations.Test;

import java.io.IOException;

public class BookTest {
    private CsvReader.Book book;

    @Factory(dataProvider = "books")
    public BookTest(CsvReader.Book book) {
        this.book = book;
        System.out.println("Created test class for the Book : " + book);
    }

    @Test
    public void authorTest() {
        Assert.assertNotNull(this.book.getAuthor());
    }

    @Test
    public void bookNameTest() {
        Assert.assertNotNull(this.book.getName());
    }

    @Test
    public void priceTest() {
        Assert.assertTrue(this.book.getPrice() > 0);
    }

    @DataProvider(name = "books")
    public static Object[][] getBooks(ITestContext context) throws IOException {
        String filename = context.getCurrentXmlTest().getParameter("filename");
        CsvReader.Book[] books = new CsvReader(filename).getBooks();
        Object[][] booksList = new Object[books.length][1];
        for (int i = 0; i < books.length; i++) {
            booksList[i][0] = books[i];
        }
        return booksList;
    }

    @Override
    public String toString() {
        return book.toString();
    }

}
TestCreatorListener.java

package com.rationaleemotions.googleforums.nested;

import org.testng.IAlterSuiteListener;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class TestCreatorListener implements IAlterSuiteListener {
    private static final String FOLDER = "src/test/resources/books";

    @Override
    public void alter(List<XmlSuite> suites) {
        XmlSuite xmlSuite = suites.get(0);
        File[] files = new File(FOLDER).listFiles(pathname -> pathname.getAbsolutePath().endsWith(".csv"));
        if (files == null) {
            files = new File[0];
        }
        List<XmlTest> xmlTests = new ArrayList<>(files.length);
        for (File file : files) {
            XmlTest xmlTest = new XmlTest(xmlSuite);
            xmlTest.setName(file.getName() + "_test");
            xmlTest.addParameter("filename", file.getAbsolutePath());
            XmlClass xmlClass = new XmlClass();
            xmlClass.setClass(BookTest.class);
            List<XmlClass> xmlClasses = Collections.singletonList(xmlClass);
            xmlTest.setClasses(xmlClasses);
            xmlTests.add(xmlTest);
        }
        xmlSuite.setTests(xmlTests);
    }
}
Suite xml 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="1265_Suite" parallel="false" verbose="2">
    <listeners>
        <listener class-name="com.rationaleemotions.googleforums.nested.TestCreatorListener"/>
    </listeners>
</suite>

Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribbings @ http://rationaleemotions.wordpress.com/

On Sat, Mar 4, 2017 at 7:00 AM, BN <[hidden email]> wrote:
Here is a situation I have and any ideas/suggestions will be great.

For example: lets say I have a file for eg. country.csv with many countries, 
usa
canada
japan

then for each of these countries, I have files like 
usa_states.csv
usa_weather.csv
usa_geography.csv

canada_states.csv
canada_weather.csv
canada_geography.csv

japan_states.csv
japan_weather.csv
japan_geography.csv

All these files have very similar data (in terms of the fields/columns) and I perform the exact same test on each of this file. So I will have 9 @test methods one for each file. I have 1 @dataprovider and feed the filename from each @test 

In the real situation, this can multiply and get pretty big.
Is there anyway, I can reduce this? I looked at the solution of combining 2 dataprovider methods, but that doesn't help because, I'm not trying to combine the 2 files
I need one value to be picked from my first csv file and then run the test for each value in the second one and the second dataprovider will be providing me with all the rows & columns of the individual files.

In a way, I think I'm looking for a nested dataprovider functionality.


--
You received this message because you are subscribed to the Google Groups "testng-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/testng-users.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "testng-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/testng-users.
For more options, visit https://groups.google.com/d/optout.
Loading...