Calling data from one class to another class - framework for JUnit - selenium-webdriver

Please forgive me as I am still very new to the world of test automation. I have started out by using Selenium WebDriver with JUnit4, predominately on windows OS, although I have modified my scripts and ran them on Mac.
I want to be able to create a set of classes containing set data such as usernames, passwords, default url . Perhaps even calling them from an excel file, but for now Im happy to store the data in classes and then pass that data into other test classes. Im guessing this would be a framework of some sort.
Currently I am writing classes that all begin with something like:
public class ExampleSQATest{
public static Chromedriver chrome;
#BeforeClass
public static void launchBrowser(){
System.setProperty("webdriver.chrome.driver", "chromedriver/chromedriver.exe");
chrome = new ChromeDrievr();
}
#Test
public void aLogin(){
chrome.manage().window().maximize();
chrome.navigate().to("http://mydummywebsite.com");
new WebDriverWait(chrome, 10).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector
("input#UserName")));
WebElement username = chrome.findElementByCssSelector("input#UserName");
username.sendKeys("username");
WebElement password = chrome.findElementByCssSelector("input#Password");
password.sendKeys("password");
WebElement submit = chrome.findElementByCssSelector("input[type='submit']");
submit.click();
}
}
I will then proceed to write further test methods which requires entering data, but I'd like to be able to call this data from somewhere else that is already predefined.
Can anyone provide any suitable suggestions to investigate so I can learn. Something that is a guide or tutorial. Nothing too advanced, just something that helps me get started by advising me how to set a class of methods to be called by other classes and how it all links together as a framework.
Many thanks in advance.

One way to do this
public abstract class TestBase
{
private readonly INavigationManager navMgr;
private readonly IWindowNavigator windowNav;
private readonly ILoginManager loginMgr;
// All your stuff that is common for all the tests
protected TestBase()
{
this.navMgr = WebDriverManager.Get<INavigationManager>();
this.windowNav = WebDriverManager.Get<IWindowNavigator>();
this.loginMgr = WebDriverManager.Get<ILoginManager>();
}}
[TestFixture]
internal class QueriesTest : TestBase
{
private QueryTests queryTests;
[SetUp]
public void Setup()
{
this.queryTests = WebDriverManager.Get<QueryTests>();
// all the stuff you run specific before tests in this test class.
}
}

Assuming you have created test classes in webdriver-junit4, Use following two classes to call your test classes (Note-Import junit annotations)
1)Create test suite class as -
#RunWith(Suite.class)
#Suite.SuiteClasses({
YourTestClass1.class,
YourTestClass2.class,[you can add more tests you have created...]
})
public class TestSuiteJU {
}
2)Create class to call suite created above as-
public class TestExecution {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(TestSuiteJU .class);
}
}

Related

How to inject a Drone instance without managing its lifecycle?

I have a Graphene Page Object.
#Location("/page")
public class MyPage {
#Drone
private WebDriver driver;
// page methods using the driver
}
And a Test Class that uses the page object.
#RunWith(Arquillian.class)
public class MyTest {
#Test
public void test(#InitialPage MyPage page) {
// use page & assert stuff
}
#Test
public void anotherTest(#InitialPage MyPage page) {
// use page & assert stuff even harder
}
}
Now, I've decided that MyTest should use method scoped Drone instances. So I add...
public class MyTest {
#Drone
#MethodLifecycle
private WebDriver driver;
Now when I run the test I get two browsers and all tests end with errors. Apparently this lifecycle management is treated as a qualifier too.
Yes, adding #MethodLifecycle in MyPage too helps. But this is not a solution - a page shouldn't care about this and should work in any WebDriver regardless of its scope. Only tests have the knowledge to manage the drone lifecycles. A page should just use whatever context it was invoked in. How can I achieve that?
This may be the answer:
public class MyPage {
#ArquillianResource
private WebDriver driver;
But I'm afraid that this skips some Drone-specific enriching. Also not sure if it will correctly resolve when there are multiple Drone instances.

Running a whole scenario before another scenario

I'm not able to figure out how to run a whole scenario before an other scenario, so that my test are not dependant on eachother.
I have this imaginary scenarios.
Scenario A
Given I have something
When I sumbit some data
I should see it on my webpage
Scenario B
Given SCENARIO A
When I delete the data
I should not see it on my webpage
When I run this scenario case, the software does not recognize Scenario A in scenario B, and ask me to create the step, like this...
You can implement missing steps with the snippets below:
#Given("^Registrere formue og inntekt$")
public void registrere_formue_og_inntekt() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
You could either:
Use a Background to group all the steps that need to be executed before the different scenarii:
Background:
Given I have something
When I submit some data
Then I should see it on my webpage
Scenario: B
When I delete the data
Then I should not see it on my webpage
Group them as part of a step definition:
#Given("^Scenario A")
public void scenario_A() {
I_have_something();
I_submit_some_data();
I_should_see_it_on_my_page();
}
which you can then use like this:
Given Scenario A
When I delete the data
Then I should not see it on my webpage
Using this technique, you usually observe that some actions are constantly reused, and you may want to factor them out so that they can be reused across different step definitions; at that point, the Page Object pattern comes very handy.
Cucumber scenarios are supposed to be independent. A lot of work is done assuming and ensuring that independence. Trying to go against will be an obstacle course.
Having said that, you could create your custom implementation of the Cucumber JUnit runner. Having this custom implementation, and by looking at the source of the original runner, you can expose / wrap / change the internals to allow what you want. For example with the following runner:
public class MyCucumber extends Cucumber {
private static Runtime runtime;
private static JUnitReporter reporter;
private static List<CucumberFeature> features;
public MyCucumber(Class<?> clazz) throws InitializationError, IOException {
super(clazz);
}
#Override
#SuppressWarnings("static-access")
protected Runtime createRuntime(ResourceLoader resourceLoader,
ClassLoader classLoader, RuntimeOptions runtimeOptions)
throws InitializationError, IOException {
this.runtime = super.createRuntime(resourceLoader, classLoader, runtimeOptions);
this.reporter = new JUnitReporter(runtimeOptions.reporter(classLoader), runtimeOptions.formatter(classLoader), runtimeOptions.isStrict());
this.features = runtimeOptions.cucumberFeatures(resourceLoader);
return this.runtime;
}
public static void runScenario(String name) throws Exception {
new ExecutionUnitRunner(runtime, getScenario(name), reporter).run(new RunNotifier());
}
private static CucumberScenario getScenario(String name) {
for (CucumberFeature feature : features) {
for (CucumberTagStatement element : feature.getFeatureElements()) {
if (! (element instanceof CucumberScenario)) {
continue;
}
CucumberScenario scenario = (CucumberScenario) element;
if (! name.equals(scenario.getGherkinModel().getName())) {
continue;
}
return scenario;
}
}
return null;
}
}
You can setup your test suite with:
#RunWith(MyCucumber.class)
public class MyTest {
}
And create a step definition like:
#Given("^I first run scenario (.*)$")
public void i_first_run_scenario(String name) throws Throwable {
MyCucumber.runScenario(name);
}
It is a fragile customization (can break easily with new versions of cucumber-junit) but it should work.

How to run all cucumber functional automated test cases in single browser

I am new to cucumber testing as well as selenium testing.Please help me to run all cucumber test cases in single browser.As for now i am creating new WebDriver object in each cucumber step_def for feature file.
The solution is, Using / passing the same Web Driver object across your step_def. From your Question i assume, you have multiple Step Def files, If the stories are small and related put all of them in a single step_def file and have a single Web driver object. If it is not the case, invoke every step_def with a predefined Driver object that is globally declared in the configuration loader.
For using one browser to run all test cases use singleton design pattern i.e make class with private constructor and define class instance variable with a private access specifier.Create a method in that class and check that class is null or not and if it is null than create a new instance of class and return that instance to calling method.for example i am posting my code.
class OpenBrowserHelp {
private WebDriver driver;
private static OpenBrowserHelp browserHelp;
private OpenBrowserHelp() {
this.driver = new FirefoxDriver()
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
public static OpenBrowserHelp getOpenBrowserHelp() {
if (null == browserHelp) {
browserHelp = new OpenBrowserHelp();
}
return browserHelp;
}
WebDriver getDriver() {
return driver
}
void setDriver(WebDriver driver) {
this.driver = driver
}
public void printSingleton() {
System.out.println("Inside print Singleton");
}
Now, where ever you need to create browser instance than use
WebDriver driver = OpenBrowserHelp.getOpenBrowserHelp().getDriver();

Apex error: "Save error: Method does not exist or incorrect signature"

I'm currently learning apex (using the Force.com IDE), and I'm running into some trouble when writing a test for a custom controller.
The controller class is as follows:
public with sharing class CustomController {
private List<TestObject__c> objects;
public CustomController() {
objects = [SELECT id, name FROM TestObject__c];
}
public List<TestObject__c> getObjects() {
return objects;
}
}
and the test class is:
#isTest
private class ControllerTest {
static testMethod void customControllerTest() {
CustomController controller = new CustomController();
System.assertNotEquals(controller, null);
List<TestObject__c> objects;
objects = controller.getObjects();
System.assertNotEquals(objects, null);
}
}
On the objects = controller.getObjects(); line I'm getting an error which says:
Save error: Method does not exist or incorrect signature: [CustomController].getObjects()
Anyone have an idea as to why I'm getting this error?
A nice shorthand:
public List<TestObject__c> objects {get; private set;}
It creates the getter/setter for you and looks cleaner imo. As for your current issue, yes - it's hard saving code directly into production - especially with test classes in separate files.
Best to do this in a sandbox/dev org then deploy to production (deploy to server - Force.com IDE). But if you must save directly into production then I'd combine test methods with your class. But in the long run, having #test atop a dedicated test class is the way to go. It won't consume your valuable resources this way.

Android Unit Tests Requiring Context

I am writing my first Android database backend and I'm struggling to unit test the creation of my database.
Currently the problem I am encountering is obtaining a valid Context object to pass to my implementation of SQLiteOpenHelper. Is there a way to get a Context object in a class extending TestCase? The solution I have thought of is to instantiate an Activity in the setup method of my TestCase and then assigning the Context of that Activity to a field variable which my test methods can access...but it seems like there should be an easier way.
You can use InstrumentationRegistry methods to get a Context:
InstrumentationRegistry.getTargetContext() - provides the application Context of the target application.
InstrumentationRegistry.getContext() - provides the Context of this Instrumentation’s package.
For AndroidX use InstrumentationRegistry.getInstrumentation().getTargetContext() or InstrumentationRegistry.getInstrumentation().getContext().
New API for AndroidX:
ApplicationProvider.getApplicationContext()
You might try switching to AndroidTestCase. From looking at the docs, it seems like it should be able to provide you with a valid Context to pass to SQLiteOpenHelper.
Edit:
Keep in mind that you probably have to have your tests setup in an "Android Test Project" in Eclipse, since the tests will try to execute on the emulator (or real device).
Your test is not a Unit test!!!
When you need
Context
Read or Write on storage
Access Network
Or change any config to test your function
You are not writing a unit test.
You need to write your test in androidTest package
Using the AndroidTestCase:getContext() method only gives a stub Context in my experience. For my tests, I'm using an empty activity in my main app and getting the Context via that. Am also extending the test suite class with the ActivityInstrumentationTestCase2 class. Seems to work for me.
public class DatabaseTest extends ActivityInstrumentationTestCase2<EmptyActivity>
EmptyActivity activity;
Context mContext = null;
...
#Before
public void setUp() {
activity = getActivity();
mContext = activity;
}
... //tests to follow
}
What does everyone else do?
You can derive from MockContext and return for example a MockResources on getResources(), a valid ContentResolver on getContentResolver(), etc. That allows, with some pain, some unit tests.
The alternative is to run for example Robolectric which simulates a whole Android OS. Those would be for system tests: It's a lot slower to run.
You should use ApplicationTestCase or ServiceTestCase.
Extending AndroidTestCase and calling AndroidTestCase:getContext() has worked fine for me to get Context for and use it with an SQLiteDatabase.
The only niggle is that the database it creates and/or uses will be the same as the one used by the production application so you will probably want to use a different filename for both
eg.
public static final String NOTES_DB = "notestore.db";
public static final String DEBUG_NOTES_DB = "DEBUG_notestore.db";
First Create Test Class under (androidTest).
Now use following code:
public class YourDBTest extends InstrumentationTestCase {
private DBContracts.DatabaseHelper db;
private RenamingDelegatingContext context;
#Override
public void setUp() throws Exception {
super.setUp();
context = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_");
db = new DBContracts.DatabaseHelper(context);
}
#Override
public void tearDown() throws Exception {
db.close();
super.tearDown();
}
#Test
public void test1() throws Exception {
// here is your context
context = context;
}}
Initialize context like this in your Test File
private val context = mock(Context::class.java)

Resources