-1

I am currently writing Selenium WebDriver tests for a variety of websites each using the same proprietary framework.

Because of this, there are many test cases that can be quite similar across different websites. As such I have made my test classes as generic as possible and made it so that every XPath/CSS Selector/ID used to locate elements is defined in a Constants class, which is unique to every project.

But, in some cases, the code for the same test can be the same across different websites, since I wrote them generically. In addition each test is a direct/indirect extension of a BasicTest class which contains code that is likely to be reused by different tests (ex: WebDriver instance declaration, etc)

The way I thought about setting my test structure was the following:

  • one generic project that is "reused" by each subsequent project;
  • one project per website with its own definition of the Constantsclass and a TestSuite class that it can use to run both generic tests and tests specific to itself.

This would allow me not to have copies of these generic tests in each of my test projects.

The problem is that I don't really know how to set this up. The GenericProject is going to contain tests that require variables from Constant, but it makes no sense to have generic Constants. Plus, will I be able to call those tests inside my website project-specific TestSuites? If I redefine Constants in each specific project, will those constants be used for the generic tests defined in GenericProject? How can I even set it up so that I can reuse Project A's classes inside of Project B, C, D... etc?

Grumbunks
  • 1,027
  • 1
  • 7
  • 21
  • Don't put the paths in a class. Define them in a properties file. Each project will have its own properties file. The keys of the properties file can be constants. – RealSkeptic Oct 29 '19 at 14:52
  • @RealSkeptic I don't think I can do that because some of my constants are derived from the values of other constants, which I don't think is doable with properties. – Grumbunks Oct 29 '19 at 15:01
  • Do you mean "How can I share ProjectA/src/test/java with tests in other modules?" – drekbour Oct 29 '19 at 15:02
  • @drekbour I'm not very familiar with the way Java projects are typically set up. At the moment I have GenericProject/src/test/java, which contains tests, that I would like to be able to share with ProjectA/src/test/java, ProjectB/src/test/java, etc. – Grumbunks Oct 29 '19 at 15:03
  • Sharing test code can be accomplished like this: https://maven.apache.org/plugins/maven-jar-plugin/examples/create-test-jar.html – drekbour Oct 29 '19 at 15:09
  • Values that are derived from other values can be calculated and cashed when the properties are loaded the first time. That shouldn't be a problem. Have an object that loads the properties, and initializes the values for the derived values, then use that object. – RealSkeptic Oct 29 '19 at 16:14

2 Answers2

1
  • Extract your constants to a properties file which exists in each module as src/test/resources/common.properties.
  • Use org.apache.commons:commons-configuration2 PropertiesConfiguration to read this file. It will handle nested properties just fine.
  • Common code can be shared by depending on your GenericModule. Official instructions for two models of doing this (extract common tests to a new module or use a test-jar) are here
drekbour
  • 2,895
  • 18
  • 28
0

In general in order to reuse code over projects you would create a library containing the reusable code. In order to do so you'd need to think about a suitable API for the library.

This contains decisions about:

  • How will functionality be called from dependent code
  • How will dependent code provide required data.

If you are using constants for e.g. CSS selectors, that are different but have the same semantics, e.g.

  • root frame
  • side panel
  • main area
  • ...

you might want to define an interface that the dependent code can provide. This could look like:

interface CssSelectors {
    String rootFrame();
    String sidePanel();
    //...
}

If you are building this for tests you might also want to use features of your test framework (e.g. Rules in JUnit).

When reusing code in tests you also should consider another aspect:

If s.o. reads the tests written with your library, will she be able to sufficiently understand what is happening behind the border of the library to understand what the test is all about? This is a lot more of a question when dealing with test code than with production code as for test coverage and validity of tests it often matters a lot more how a setup or verification is done than is the case for production code.

Christian Frommeyer
  • 1,390
  • 1
  • 12
  • 20