When using JUnit's @Parameterized, can I have some tests still run only once [duplicate]
Asked Answered
W

4

58

I use @Parameterized in many cases to run tests on a number of permutations. This works very well and keeps the test-code itself simple and clean.

However sometimes I would like to have some of the test-methods still run only once as they do not make use of the parameters, is there a way with JUnit to mark the test-method as "singleton" or "run-once"?

Note: This does not concern running single tests in Eclipse, I know how to do that :)

Warfarin answered 25/9, 2015 at 6:45 Comment(2)
It sounds like those tests shouldn't be in the same suite as the parameterized tests, then.Bondage
yep, that's the only solution that came to my mind, but I really like to have "related" tests in one suite, e.g. all tests for one class in one test-class...Warfarin
Z
14

You can associate any number of test classes to run together using a suite. This way all the tests are run when you test your class and you can mix different test runners.

  1. Create a test suite associated with the class you are testing
  2. Add a reference to the parameterized test class
  3. Add the other class(es) containing non parameterized tests.

    import org.junit.runners.Suite;
    import org.junit.runner.RunWith;
    
    @RunWith(Suite.class)
    @Suite.SuiteClasses({ParameterizedTestClass.class, UnitTests.class, MoreUnitTests.class})
    public class SutTestSuite{
         //Empty...
    }
    
Zuckerman answered 25/9, 2015 at 7:3 Comment(1)
Yeah, that's propably what I will end up with, I hoped there would be something like an annotation for single test-methods...Warfarin
C
119

You could structure your test with the Enclosed runner.

@RunWith(Enclosed.class)
public class TestClass {

    @RunWith(Parameterized.class)
    public static class TheParameterizedPart {

        @Parameters
        public static Object[][] data() {
            ...
        }

        @Test
        public void someTest() {
            ...
        }

        @Test
        public void anotherTest() {
            ...
        }
    }

    public static class NotParameterizedPart {
        @Test
        public void someTest() {
            ...
        }
    }
}
Cytology answered 28/1, 2016 at 9:32 Comment(1)
Nice! Didn't know about Enclosed. Thanks!Pearlinepearlman
Z
14

You can associate any number of test classes to run together using a suite. This way all the tests are run when you test your class and you can mix different test runners.

  1. Create a test suite associated with the class you are testing
  2. Add a reference to the parameterized test class
  3. Add the other class(es) containing non parameterized tests.

    import org.junit.runners.Suite;
    import org.junit.runner.RunWith;
    
    @RunWith(Suite.class)
    @Suite.SuiteClasses({ParameterizedTestClass.class, UnitTests.class, MoreUnitTests.class})
    public class SutTestSuite{
         //Empty...
    }
    
Zuckerman answered 25/9, 2015 at 7:3 Comment(1)
Yeah, that's propably what I will end up with, I hoped there would be something like an annotation for single test-methods...Warfarin
S
1

there is a number of junit plugins that give you some more features/power regarding parameterized tests. check zohhak, junit-parames and junit-dataprovider. they allow you to mix parametrized and simple junit tests

Silverfish answered 25/9, 2015 at 8:39 Comment(0)
C
1

Before I knew about "@RunWith(Enclosed.class)" approach, I used the following (similar) solution, with inner classes extending outer class. I keep using this structure because I like that the tests are in same place and share some properties and methods and things seems clearer to me. Then, using Eclipse, in my run configuration, I choose that option "Run all tests in the selected project, package or source folder" and all these tests will be performed with just a click.

public class TestBooksDAO {

    private static BooksDAO dao;

    @Parameter(0)
    public String title;
    @Parameter(1)
    public String author;

    @Before
    public void init() {
        dao = BooksDAO.getInstancia();
    }

    /** Tests that run only once. */
    public static class SingleTests extends TestBooksDAO {

        @Test(timeout=10000)
        public void testGetAll() {
            List<Book> books = dao.getBooks();
            assertNotNull(books);
            assertTrue(books.size()>0);
        }

        @Test(timeout=10000)
        public void testGetNone() {
            List<Book> books = dao.getBooks(null);
            assertNull(books);
        }
    }

    /** Tests that run for each set of parameters. */
    @RunWith(Parameterized.class)
    public static class ParameterizedTests1 extends TestBooksDAO {

        @Parameters(name = "{index}: author=\"{2}\"; title=\"{0}\";")
        public static Collection<Object[]> values() {
            return Arrays.asList(new Object[][] { 
                {"title1", ""}, 
                {"title2", ""}, 
                {"title3", ""}, 
                {"title4", "author1"}, 
                {"title5", "author2"}, 
            });
        }

        @Test(timeout=10000)
        public void testGetOneBook() {
            Book book = dao.getBook(author, title);
            assertNotNull(book);
        }
    }

    /** Other parameters for different tests. */
    @RunWith(Parameterized.class)
    public static class ParameterizedTests2 extends TestBooksDAO {

        @Parameters(name = "{index}: author=\"{2}\";")
        public static Collection<Object[]> values() {
            return Arrays.asList(new Object[][] { 
                {"", "author1"}, 
                {"", "author2"}, 
                {"", "author3"}, 
            });
        }

        @Test(timeout=10000)
        public void testGetBookList() {
            List<Book> books = dao.getBookByAuthor(author);
            assertNotNull(books);
            assertTrue(books.size()>0);
        }
    }
}
Clapp answered 18/1, 2017 at 4:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.