JUnit passing parameters between class - java

I have a scenario as follows that I'm not sure from where to start,
File name should be passed as an argument param when running the jar file
say for example I want to test a set of data from external file and I have a super class (Test Suite) that have number one and number two
and there are two test classes that should extend this class and perform the tests.
I'm currently new to JUnit so I'm lacking many concepts and need someone's help.
I have class CoreManager which executes the main
public static void main(String[] args)
{
if (Arrays.asList(args).contains("Import"))
{
accountInfo = new ArrayList<>();
int ImportIndex = Arrays.asList(args).indexOf("Import");
String fileName = args[ImportIndex+1];
if (fileName.contains("xml"))
{
ParseXML parseXML = new ParseXML();
accountInfo = parseXML.ParseAccounts(fileName);
Result result = JUnitCore.runClasses(LoginTestSuite.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}
}
And Suite Class
#RunWith(MockitoJUnitRunner.class)
#Suite.SuiteClasses({
Login.class,
SignUp.class
})
public class LoginTestSuite {
public static WebDriver driver;
public static ArrayList<AccountInfo> Account;
public static int SecondsToWait;
public LoginTestSuite(WebDriver driver,ArrayList<AccountInfo> Account,int
secondsToWait)
{
this.Account = Account;
this.SecondsToWait = secondsToWait;
this.driver = driver;
}
}
And Test Class
public class Login {
private static WebDriver driver;
private static ArrayList<AccountInfo> Account;
private static int SecondsToWait;
private static final Logger logger = Logger.getLogger(Login.class.getName());
#BeforeClass
public void init(){
this.driver = LoginTestSuite.driver;
this.Account = LoginTestSuite.Account;
this.SecondsToWait = LoginTestSuite.SecondsToWait;
}
#Before
public void Setup(){
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(SecondsToWait,
TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(SecondsToWait,
TimeUnit.SECONDS);
}
#After
public void TearDown(){
driver.quit();
}
#Test
public void TestUserLogin() throws Exception
{
// Logic
}

Your code looks muddled and contains several poor quality constructs. Most importantly, I don't see a distinction between test code and production code. Which is which?
This could be production code:
public class App {
public static void main(String[] args) {
AccountReader accountReader = new AccountReader();
List<AccountInfo> accounts = accountReader.read(args);
// maybe do something with those accounts?
}
}
public class AccountReader {
private ParseXML parseXML;
public AccountReader() {
this.parseXML = new ParseXML();
}
// extra constructor to allow dependency injection from test
protected AccountReader(ParseXML parseXML) {
this.parseXML = parseXML;
}
public List<AccountInfo> read(String[] args) {
return parseXML.ParseAccounts(getFileName(args));
}
private String getFileName(String[] args) {
List<String> arguments = Arrays.asList(args);
int importIndex = arguments.indexOf("Import");
if (importIndex < 0) {
throw new RuntimeException("Missing Import argument");
}
int fileNameIndex = importIndex + 1;
if (fileNameIndex >= arguments.size()) {
throw new RuntimeException("Missing fileName argument");
}
String fileName = args[fileNameIndex];
if (!fileName.endsWith(".xml")) {
throw new RuntimeException("Can only import XML files");
}
return fileName;
}
}
And this could be a test for it:
public AccountReaderTest {
private AccountReader instance;
#Mock // creates a mock instance which we can give desired behavior
private ParseXML parseXML;
#Mock
List<AccountInfo> accounts;
#Before
public void setUp() {
instance = new AccountReader(parseXML);
}
#Test
public void testHappy() {
// SETUP
String fileName = "test.xml";
// specify desired behavior of mock ParseXML instance
when(parseXML.ParseAccounts(fileName).thenReturn(accounts);
// CALL
List<AccountInfo> result = instance.read(new String[] { "Import", fileName });
// VERIFY
assertEquals(accounts, result);
}
#Test(expected = RuntimeException.class)
public void testMissingImport() {
instance.read(new String[] { "notImport" });
}
#Test(expected = RuntimeException.class)
public void testMissingFileName() {
instance.read(new String[] { "Import" });
}
#Test(expected = RuntimeException.class)
public void testNotXml() {
instance.read(new String[] { "Import", "test.properties"});
}
}

Related

Getting Exception In Initializer error from maven- Selenium test

i am getting an Exception In Initializer error in my code and don't know what i am doing wrong, please help !i am happy to answer if you have any questions. Below is the error i am getting from maven:
[ERROR] Failures:
[ERROR] Homepage_Test.startURL:13->BaseClass.globalDriver:26 ยป ExceptionInInitializer.
//My Homepage_Test which includes all tests. startURL() invokes webdriver and runs to get website:
public class Homepage_Test extends BaseClass{
#BeforeTest
public void startURL() {
globalDriver();
}
#Test
public void search_product() {
Homepage_Methods.search_and_add();
}
#Test
public void verify_product_text() {
Homepage_Methods.verify_search();
}
#Test
public void scroll_down_page() {
Homepage_Methods.scroll_down_verify_text();
}
#AfterClass
public void clear_field() {
Homepage_Methods.clear_inputfield();
}
}
// My BaseClass:
public class BaseClass {
public static void globalDriver() {
System.setProperty("webdriver.gecko.driver" , System.getProperty("user.dir")+"/resources/geckodriver.exe");
WebDriver driver = new FirefoxDriver();
#SuppressWarnings("unused")
Shop_Page_Objects cpo = new Shop_Page_Objects(driver);
#SuppressWarnings("unused")
Homepage_Objects hpom = new Homepage_Objects(driver);
#SuppressWarnings("unused")
Shop_Page_Methods spm = new Shop_Page_Methods(driver);
#SuppressWarnings("unused")
Homepage_Methods hpm = new Homepage_Methods(driver);
DesiredCapabilities dc = new DesiredCapabilities();
FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);
dc.setCapability(FirefoxOptions.FIREFOX_OPTIONS,options);
driver.manage().timeouts().implicitlyWait(6000, TimeUnit.SECONDS);
driver.get("blabla website");
}
}
//Line 26 of BaseClass contains Shop_Page_Methods which is very long but here is the snippet:
public class Shop_Page_Methods extends BaseClass{
private static WebDriver driver;
public Shop_Page_Methods(WebDriver driver) {
Shop_Page_Methods.driver = driver ;
}
public static WebElement product_1_to_add_to_cart = Shop_Page_Objects.get_cart_product_1();
public static List<WebElement> all_products = Shop_Page_Objects.get_All_Products();
public static int products_count = Shop_Page_Objects.get_All_Products().size();
public static List<WebElement> all_price = Shop_Page_Objects.get_price();
public static String remove_number = Shop_Page_Objects.get_number_to_remove().getText();
public static String[] remover_1 = remove_number.split("");
public static int remove_number_1 = Integer.parseInt(remover_1[0]);
i figured out the issue was that i was doing the following before actually clicking/switching to their container:
public static String remove_number = Shop_Page_Objects.get_number_to_remove().getText();
public static String[] remover_1 = remove_number.split("");
public static int remove_number_1 = Integer.parseInt(remover_1[0]);

Use an object in other methods of a test class

I have a test class in Android test package. There is a class that I've create an object in it. But other method of this test class can not use this object and can not recognize the result of that method. Why and what should I do? I used static too but can't...
#RunWith(AndroidJUnit4.class)
public class PatientDaoTest {
private static int newRowId;
public static PatientRecordEntity newPatient1;
public void generationRecord(){
newRowId = 0;
PatientRecordEntity newPatient1 = new PatientRecordEntity();
newPatient1.setPatient_db_ID("23456");
newPatient1.setPatient_race("Chines");
newRowId = (int) patientDao.addNewPatient(newPatient1);
newPatient1.setPid(newRowId);
}
#Test
public void addNewPatient() throws Exception {
boolean pin = false;
if (0 != newRowId) {
pin = true;
}
assertTrue("addNewPatient is not true", pin);
}
use the annotation #Before.
like:
public class HTest {
public static Integer i;
#Before
public void before(){
i = 10;
}
#Test
public void print() {
System.out.println(i);
}
}
This before method will be executed before print and i will be Initialized.

Cannot store WebDriver as global variable and execute a test more than once in the same Swing instance

In Swing, I have a JButton which executes the following test script when clicked on:
#RunWith(Parameterized.class)
public class ExampleTest{
private static csvTools csvTools = new csvTools();
private static WebDriver driver = CreateWebDriver.getDriver("chrome");
public static URLS urls;
// ..
// Data variables
private String fullName;
// ..
public ExampleTest(Map<String, String> testDataRow) {
this.fullName = testDataRow.get("Full name");
//..
}
#Rule
public TestName currentlyRunningTest = new TestName();
#Rule
public final ErrorCollector collector = new ErrorCollector();
#Parameterized.Parameters
public static Collection<Map<String, String>> testData() throws Exception {
return csvTools.getTests("ExampleTestData.csv");
}
#BeforeClass
public static void openBrowser() throws Exception {
page = new BasePage(driver);
userInformation = new UserInformation();
loginPage = new LoginPage(driver);
registrationPage = new RegistrationPage(driver);
evidenceCollector = new resources.EvidenceCollector(ExampleTest.class.getName());
}
#Before
public void setUp() throws Exception {
csvTools.saveData(currentlyRunningTest, "Fail/Pass", "");
evidenceCollector.newTestCase();
}
#Test
public void ExampleTest() throws Exception {
try {
driver.get(URLS.LOGINPAGEURL);
driver.findElement(By.id("d"));
//..
driver.get("examplesite");
page.screenShot(driver);
}
#After
public void tearDown() throws Exception {
evidenceCollector.moveScreenshotsAndTestData("ExampleTestData.csv");
}
#AfterClass
public static void closeBrowser() {
driver.quit();
}
}
The issue I have is, it will not let me execute the same script more than twice in the same Swing GUI instance. I have identified that this line, is the culprit:
private static WebDriver driver = CreateWebDriver.getDriver("chrome");
I determied this by commenting the line out and moving:
WebDriver driver = CreateWebDriver.getDriver("chrome");
into the test itself, where it is then possible to execute the test more than once in the same Swing GUI instance. However, as the the chrome driver is no longer stored as a global variable I cannot access it outside of the test, such as as #BeforeClass and #After
Here is the GUI Code:
JButton exTest1 = new JButton("Run ExampleTest");
exTest1.setLocation(290, 70);
exTest1.setSize(120, 30);
buttonPanel.add(exTest1);
exTest1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (exTest1.isEnabled()) {
executor.execute(new Runnable() { // This is how we run stuff in background. You can use lambdas instead of Runnables.
public void run() {
JUnitCore junit = new JUnitCore();
final Result result = junit.run(ExampleTest.class);
SwingUtilities.invokeLater(new Runnable() { // Now we go back to the GUI thread
public void run() {
errorMessageDisplay(result);
}
});
}
});
}
}});
What about initializing the driver in #BeforeClass ?
#RunWith(Parameterized.class)
public class ExampleTest{
private static csvTools csvTools = new csvTools();
private static WebDriver driver;
// ...
#BeforeClass
public static void openBrowser() throws Exception {
driver = CreateWebDriver.getDriver("chrome");
page = new BasePage(driver);
// ...
}
// ...
}

why is #Parameterized.Parameters called twice?

I have this code:
#RunWith(ParallelParameterized.class)
public class RoutingResponseShortRegressionOneByOne {
...
#BeforeClass
public static void oneTimeSetUp() {
routingUrlHttpClientWithReRun = injector.getInstance(IRoutingUrlHttpClientWithReRun.class);
System.out.println("in RoutingResponseRegressionOneByOne:: oneTimeSetUp");
}
#AfterClass
public static void oneTearDown() {
// if (globalSettings.isSaveNewResponses) {
assertE2eCheckers();
stateSaver.save(e2EResultShort);
//}
}
//takes the next matrix row from OrganizeTestParameterizedInput()
public RoutingResponseShortRegressionOneByOne(String routingRequest, CompleteRoutingResponseShort
routingResponse) {
initNonStaticFromInjector();
this.routingRequest = routingRequest;
this.routingResponse = routingResponse;
}
//This is called before #BeforeClass !
#Parameterized.Parameters
public static Collection getRequests() throws IOException {
injector = Guice.createInjector(new MainModule());
initStaticFromInjector();
initTestInput();
e2EResultShort = new E2EResultShort();
return OrganizeTestParameterizedInput();
}
And it runs like this:
#Parameterized.Parameters
#Parameterized.Parameters
#BeforeClass
public RoutingResponseShortRegressionOneByOne --> ctor
#Test
why is #Parameterized.Parameters called twice in a row?
In addition, how can I know #RunWith(ParallelParameterized.class) really works? meaning how can I check if the run is in parallel?

How to cache a JUnit class field between runs with #Parameters

Lets assume the following JUnit test class:
#RunWith(Parameterized.class)
public class MyTestClass {
private ExpensiveObjectToCreate myObject;
#Parameters
public static Collection<Object[]> data() {
Object[][] data = new Object[][] {
{ "parameter1" },
{ "parameter2" },
};
return Arrays.asList(data);
}
#Test
public void test1() {
}
#Test
public void test2() {
}
public MyTestClass(String stringParameter) {
myObject = new ExpensiveObjectToCreate(stringParameter);
}
}
Is there any way for me to create the expensive object just once for every parameter set? I say this because JUnit creates a new test class for every test it needs to run. This means that the expensive object is NOT created 2 times, but actually 4 times (2 parameter sets x 2 tests). This gets even worse when we have many test methods.
Also, sending the expensive object as a parameter is not a solution for me because my scenario is a little bit more complicated (I create the expensive object in JUnit rules).
Why not just roll out a custom cacher in your test case class, which caches the instance created per parameter and returns the same instance on further invocations.
#RunWith(Parameterized.class)
public class Test {
private static ExpensiveObjectCacher cacher; //instance which caches parameter instance
private ExpensiveObject myObject;
public Test(String value) {
this.myObject = cacher.get(value);
}
#BeforeClass
public static void setUpBeforeClass(){
cacher = new ExpensiveObjectCacher();
}
#Parameters
public static Collection<Object[]> data() {
Object[][] data = new Object[][] {
{ "parameter1" },
{ "parameter2" },
};
return Arrays.asList(data);
}
#org.junit.Test
public void test1(){
}
#org.junit.Test
public void test2(){
}
}
//caching for test cases.
class ExpensiveObjectCacher{
private Map<String, ExpensiveObject> map = new ConcurrentHashMap<String, ExpensiveObject>();
ExpensiveObject get(String value){
ExpensiveObject instance = map.get(value);
if(instance == null){
instance = new ExpensiveObject(value);
map.put(value, instance);
}
return instance;
}
}
class ExpensiveObject{
public ExpensiveObject(String value) {
System.out.println("Instance created: " + value);
}
}
Output:
Instance created: parameter1
Instance created: parameter2
You could work with a static Map from the parameters (here a simple string) to instances of ExpensiveObjectToCreate.
#RunWith(Parameterized.class)
public fnial class MyTestClass {
private static final Map<Parameter, ExpensiveObjectToCreate> MAPPING = new HashMap<>();
private ExpensiveObjectToCreate myEOTC;
public MyTestClass(String stringParameter) {
myEOTC = getEOTC(new Parameter(stringParameter));
}
private static getEOTC(Parameter parameter) {
ExpensiveObjectToCreate eotc = MAPPING.get(parameter);
if (eotc == null) {
eotc = new ExpensiveObjectToCreate(parameter.stringParameter);
MAPPING.put(parameter, eotc);
}
rturn eotc;
}
private static final class Parameter {
String stringParameter;
Parameter(String stringParameter) { this.stringParameter = stringParameter; }
#Override public int hashCode() { ... }
#Override public boolean equals(Object other) { ... }
}
}
However, if you also need to limit the number of expensive objects, you should do more work, for example a cache could be a solution.
If you're using Junit 4:
private static ExpensiveObjectToCreate myObject;
private static String stringParameter = "some text";
#BeforeClass
public static void setUpBeforeClass() throws Exception {
myObject = new ExpensiveObjectToCreate(stringParameter);
}
If Junit 3:
private static ExpensiveObjectToCreate myObject;
private static String stringParameter = "some text";
#BeforeClass
protected static void setUpBeforeClass() throws Exception {
myObject = new ExpensiveObjectToCreate(stringParameter);
}
In both cases the object will be created once for all the unit tests.
Edit: The String I am not sure where it came from, so I am asuming that the String is the same for all unit tests.

Categories

Resources