5

I've clubbed feature related tests in one test class. Suppose we've 50 tests in that class. Out of 50, suppose there are 5 test cases which require common test data or pre-requisites. If I create/set it in setup method of class like @BeforeClass annotation of TestNG and delete/reset in tear down method like @AfterClass, it has following drawbacks -

  1. If I want to run single test or tests, which does/do not belong to those 5 tests, still it'll perform create/set operations which are irrelevant to this test.
  2. Also it confuses new tester which data is for which tests. Unnecessarily makes him to think what @BeforClass is doing for all following tests.
  3. If data/set up only required for specific tests, system should be retain to earlier state after those tests are executed. This statement also fails here.

Is following better approach to handle this -

Even though 5 tests require same setup and test data, we should create/set it for each test and remove/reset it after that test is run.

But this also has drawback - this will increase execution time.

Please suggest what is best approach used in such cases.

NOTE: These five test cases are such that those cannot be handled with data provider.

4 Answers 4

5

Suggestion 3 (following FDM's 2): Extract the tests that need the extra setup into a separate class.

Suggestion 4: Put the special tests into a group. Put the special setup into its own @BeforeGroups method that runs just before the special tests' group.

2
  • I think #4 is the best solution, didn't know that because I don't use TestNG myself. I didn't include #3 because if that would be possible, OP didn't need to ask the question in the first place. :D
    – FDM
    Jun 15, 2017 at 9:59
  • 1
    50 tests in one class is pretty hard to read. I would split them into 2 or more classes anyway.
    – dzieciou
    Jun 15, 2017 at 10:32
1

Supposing that your tests must all remain in a single class:

Suggestion 1: retrieve your test name in BeforeMethod and AfterMethod methods like so. Then use logic (if/else, switch) to determine which set-up or teardown actions to take, depending on the case which is running.

Suggestion 2: write a private initialize method in your test class. Then call this method as the first step in the related tests only.

2
  • Name one valid reason why tests must stay in one class? Be proactive, take control. It is your code, choose to use multiple classes. Jun 15, 2017 at 11:24
  • There is none, but OPs question is BECAUSE they are in a single class. If he could solve the issue simply by splitting classes, I should hope he would've done so.
    – FDM
    Jun 15, 2017 at 11:31
0

Two factors I would consider:

  • Whether to repeat the setup for each of the 5 tests. The answer here is usually yes. We've learned over time that once you are not 100 sure about starting and ending state, due to shared data, bad things happen and bugs become very hard to diagnose. It may seem unnecessary to recreate reference data every time but it is the cleanest solution. When data is shared among all tests and no test every changes it may be ok to share it. For example zip code reference file - however it is also preferable to test specific zip codes - perhaps 5-10, rather than using a reference file that may contain 100,000 entries.

  • It is important to have readable tests. When multiple tests share setup you can often structure the tests so that the setup which is shared is only defined once. This is done like this:

    setup for all tests (separate files)
    
    setup for all tests in the file
    
      setup up for a group of tests within a file
    
        setup up for a subgroup of tests(...)
    
          setup for a individual tests
    

    Note that for each individual test ALL the defined setups will run and after each test, full teardown should occur

0

I dislike setup methods for test-data and such, as they keep the cause and effect separated, possibly leading to unclear effects when reading the tests. Read the Google testing on the toilet: Keep cause and effect clear.

Create your own setup-methods, don't use methods that get called automatically by the unit-testing framework. Here an example:

testExampleForSomeBehavior() {
  // Arrange
  callAMethodToSetupTestDataSpecificForThisTestItCreatesUsersAndTestData()
  // Act
  steps to execute behavior...
  // Assert
  verify behavior
}

If you have 50 tests in your class this means if you put the code of callAMethodToSetupTestData() into the regular setup methods you need to scroll up to understand the test. Better to group it into another method and give it a good and clear name that describes the test-data. The only code that goes into the setup() is something you need for all your tests, e.g. creating a browser instance or a database connection.

Also I would create more classes. Name your tests classes after the behavior they test. Keep it clean. Clean code is easy to read and understand. Just putting more and more tests in one class is the classic large-class code-smell for me. Not all tests test the same behavior or application part probably. 50 just sounds like a lot of test for a single behavior, maybe you also have a lot of test-duplication, maybe you can remove some tests while keeping the same functional coverage. Also I tend to separate unit, integration and functional-tests into different classes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.