I have some WebdriverSelenium/TestNG/Maven/Java continuous integration tests, that I refactored (removed a huge chain of inheritances) and now I've also installed Spring DI framework.
I just cant pass the parameters to the Test method (oneUserTwoUser)
This is the dataprovider
public class AppData {
public static WebDriver driver;
public static WebDriverWait wait;
final static String FILE_PATH = "src/test/resources/250.csv";
final static String FILE_PATH2 = "src/test/resources/places.csv";
public static ArrayList<ArrayList<String>> array;
public static Object[][] setUp() throws Exception {
//prepare data
//read data from CSV files
array = getCSVContent(FILE_PATH, 5);
array2 = getCSVContent(FILE_PATH2, 7);
//pass the data to the test case
Object[][] setUp = new Object[1][3];
setUp[0][0] = driver;
setUp[0][1] = wait;
setUp[0][2] = array;
return setUp;
}
This is the test class:
public class AppTest3 {
public static AppData appdata;
public static void main (String[] args) {
BeanFactory beanfactory = new XmlBeanFactory(new FileSystemResource("spring.xml"));
appdata = (AppData) beanfactory.getBean("data");
}
#Parameters({ "driver", "wait", "array" })
#Factory(dataProviderClass = AppData.class, dataProvider = "setUp")
#Test
public void oneUserTwoUser(WebDriver driver, WebDriverWait wait, ArrayList<ArrayList<String>> array) throws Exception {
Error
org.testng.TestNGException:
Parameter 'driver' is required by #Test on method oneUserTwoUser but has not been marked #Optional or defined
As described by the documentation:
Preface your setUp() function with #DataProvider(name="standardTestData")
Then remove all other annotations except for #Test(dataProvider="standardTestData", dataProviderClass=AppData.class)
Related
I am trying to test my mongodb dao using embedded mongodb- but the test data is not being created.
By contrast, if I use the same way to creating objects in real db then it works OK.
This is my config:
public class UnmappableDataDAOTest
{
private static final String LOCALHOST = "127.0.0.1";
private static final String DB_NAME = "itest";
private static final int MONGO_TEST_PORT = 27028;
private static final String CONTRACT_COLLECTION = "ContractAnswers";
private UnmappableDataDAO dao;
private static MongodProcess mongoProcess;
private static Mongo mongo;
private MongoTemplate template;
#BeforeClass
public static void initializeDB() throws IOException
{
RuntimeConfig config = new RuntimeConfig();
config.setExecutableNaming(new UserTempNaming());
MongodStarter starter = MongodStarter.getInstance(config);
MongodExecutable mongoExecutable = starter.prepare(new MongodConfig(Version.V2_2_0, MONGO_TEST_PORT, false));
mongoProcess = mongoExecutable.start();
mongo = new Mongo(LOCALHOST, MONGO_TEST_PORT);
mongo.getDB(DB_NAME);
}
#AfterClass
public static void shutdownDB() throws InterruptedException {
mongo.close();
mongoProcess.stop();
}
#Before
public void setUp() throws Exception {
dao = new UnmappableDataDAO();
template = new MongoTemplate(mongo, DB_NAME);
dao.setMongoOperations(template);
}
#After
public void tearDown() throws Exception
{
template.dropCollection(ContractAnswers.class);
}
#Test
public void testCreate()
{
// Setup Test Data
List<ContractAnswers> contractAnswersList = new ArrayList<>();
ContractAnswers first = new ContractAnswers();
first.setContractId(1L);
first.setTemplateName("firstTemplate");
first.setId("1");
contractAnswersList.add(first);
ContractAnswers second = new ContractAnswers();
second.setContractId(2L);
second.setTemplateName("secondTemplate");
second.setId("2");
contractAnswersList.add(second);
for (ContractAnswers contractAnswers : contractAnswersList)
{
template.save(contractAnswers, CONTRACT_COLLECTION);
}
ContractAnswers third = new ContractAnswers();
third.setContractId(3L);
third.setTemplateName("thirdTemplate");
third.setId("3");
dao.create(third);
List<ContractAnswers> list = template.findAll(ContractAnswers.class);
}
}
The result of findAll() method is null. That means, that data has not been created.
When I use this way of creation: template.save(contractAnswers, CONTRACT_COLLECTION);, test data is created, but I need the way with CONTRACT_COLLECTION as a parameter. All methods in my dao depend on it.
It is strange, but this is how my create method looks like and it works OK:
public void createOrUpdate(ContractAnswers contractAnswers)
{
this.mongoOperations.save(contractAnswers, CONTRACT_COLLECTION);
}
The same code works ok in real database, but not work in test.
Thank you.
I have about 15 JUnit test cases each one which needs a difference resource file from which it reads necessary input data. Currently, I'm hard coding the specific resource file path in each test case method.
#Test
public void testCase1() {
URL url = this.getClass().getResource("/resource1.txt");
// more code here
}
#Test
public void testCase2() {
URL url = this.getClass().getResource("/resource2.txt");
// more code here
}
May be I could have all these files loaded in the setUp() method into separate URL variables and then use the specific URL variable in each test method. Is there a way better way of doing this?
You can use the TestName rule.
#Rule public TestName testName = new TestName();
public URL url;
#Before
public void setup() {
String resourceName = testName.getMethodName().substring(4).toLowerCase();
url = getClass().getResource("/" + resourceName + ".txt");
}
#Test
public void testResource1() {
// snip
}
#Test
public void testResource2() {
// snip
}
Try JUnit RunWith(Parameterized.class).
Example, that takes a resource name and an int expected result :
#RunWith(Parameterized.class)
public class MyTest {
#Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{"resource1.txt", 0000}, {"resource2.txt", 9999}
});
}
public final URL url;
public final int expected;
public MyTest(String resource, int expected) {
this.url=URL url = this.getClass().getResource("/"+resource)
this.expected = expected;
}
#Before
public void setUp() {
}
#Test
public void testReadResource() throws Exception {
// more code here, based on URL and expected
}
}
More info here:http://junit.org/apidocs/org/junit/runners/Parameterized.html
I am trying to create a framework to test cross-platform mobile web apps (non native). Here is how my code is setup:
Test Class:
public class TestSuite extends MobileLibrary{
#BeforeClass
public static void setUpTests() throws Exception {
setUp();
}
#AfterClass
public static void cleanUpTests() throws Exception {
driver.quit();
}
#Test
public void validateSignIn() throws Exception
{
String username = "testtest";
String password = "testtest";
SignInMobile(driver,username,password);
assertTrue(true);
}
#Test
public void randomTests() throws Exception
dbcSelector(driver,"test");
assertTrue(true);
}
}
Base Class
public class SetupBase
{
protected static AppiumDriver driver;
protected static AppiumPlatform appiumPlatform;
protected static DeviceSize deviceSize;
protected static DeviceName deviceName;
protected static String deviceID;
protected static DesiredCapabilities capabilities;
protected static enum AppiumPlatform{
DESKTOP,IOS,ANDROID
}
protected static enum DeviceSize{
SMALL,MEDIUM,LARGE
}
protected static enum DeviceName{
NEXUS7,S5,IPHONE5S
}
public static void setUp() throws MalformedURLException /*throws Exception*/ {
String deviceNameEnv = System.getenv("DEVICENAME");
switch(deviceNameEnv){
//sets devicename here
}
//sets platform here
if(deviceName==DeviceName.NEXUS7 || deviceName==DeviceName.S5)
appiumPlatform = AppiumPlatform.ANDROID;
else if(deviceName==DeviceName.IPHONE5S)
appiumPlatform = AppiumPlatform.IOS;
else
appiumPlatform = AppiumPlatform.DESKTOP;
switch(deviceName){
//sets size here
}
capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName",deviceID);
if(appiumPlatform==AppiumPlatform.ANDROID){
capabilities.setCapability("platformName","Android");
capabilities.setCapability("browserName","Chrome");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
else if(appiumPlatform==AppiumPlatform.IOS){
capabilities.setCapability("platformName","iOS");
capabilities.setCapability("browserName","Safari");
driver = new IOSDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
}
}
No matter what I do, any time I try to use driver in the second test I will get a java null pointer exception. MobileLibrary extends the baseclass and contains all my WebDriver element functions.
Edit: If I directly do driver.findelement in my second test I get an element not found exception. It looks like something is being reset after the end of a #test and I have no idea what.
I found out that the problem was actually with the #test order execution. I didn't realize that junit doesn't run tests in order, I'll be looking into the test suite fixtures.
3 weeks of experience with Java here.
I have these two classes - AppTest and AppTest2 and I have the same code in both of them:
Here is my code:
public class Apptest/AppTest2 {
public WebDriver driver;
public WebDriverWait wait;
#DataProvider(name = "dataProvider")
public Object[][] setUp() throws Exception {
File firefoxPath = new File(System.getProperty("lmportal.deploy.firefox.path", "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe"));
FirefoxBinary ffox = new FirefoxBinary(firefoxPath);
ffox.setEnvironmentProperty("DISPLAY", ":20");
driver = new FirefoxDriver(ffox, null);
wait = new WebDriverWait(driver, timeoutInSeconds );
Object[][] data = new Object[1][2];
data[0][0] = driver;
data[0][1] = wait;
return data;
}
#Parameters({ "driver", "wait" })
#Test(dataProvider = "dataProvider")
public void twoUsersSignUp(WebDriver driver, WebDriverWait wait) throws InterruptedException{
//test here
}
}
How can I take this code out (setUp()), make it a class and then pass those variables to the next void "twoUsersSignUp"
EDIT: Im not looking for automatic solution, I just want to refactor this, so I dont have the same code in both classes
EDIT2: After I implemented the accepted answer's solution, I now have a problem with passing the variable "driver" to the next method in the first class:
#AfterClass
public void quit () {
driver.quit();
}
How do I do that?
EDIT3: This is the #AfterClass solution:
#SuppressWarnings("deprecation")
#Configuration
#AfterClass
public static void quit (#Optional WebDriver driver) {
driver.quit();
}
EDIT4: actually EDIT3 doesnt work, it just hides the errors from Eclipse. I still can't access "driver" :(
EDIT5: I decided that I dont need to have it in an AfterClass TestNG annotation, so I removed all the unnecessary stuff and it now looks like this:
public static void quit (WebDriver driver) {
driver.quit();
}
and the variable has been declared this way:
public static WebDriver driver;
but still it doesnt work
EDIT6: fixed this by actually calling the method in the test code. Beforehand I didnt have to call it, because testng.xml had it called, but after I removed the #AfterTest annotation, it had been excluded from there!
You cannot convert a method to a class, but you can move a method to a place from which it would be shared by both Apptest and AppTest2: create a base class, and make the Apptest and AppTest2 classes extend it.
public abstract class AbstractAppTest {
public WebDriver driver;
public WebDriverWait wait;
#DataProvider(name = "dataProvider")
public Object[][] setUp() throws Exception {
File firefoxPath = new File(System.getProperty("lmportal.deploy.firefox.path", "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe"));
FirefoxBinary ffox = new FirefoxBinary(firefoxPath);
ffox.setEnvironmentProperty("DISPLAY", ":20");
driver = new FirefoxDriver(ffox, null);
wait = new WebDriverWait(driver, timeoutInSeconds );
Object[][] data = new Object[1][2];
data[0][0] = driver;
data[0][1] = wait;
twoUsersSignUp(data);
return data;
}
public abstract void twoUsersSignUp(#Optional Object[][] data) throws InterruptedException;
}
public class Apptest extends AbstractAppTest {
public void twoUsersSignUp(#Optional Object[][] data) throws InterruptedException {
...
}
}
public class AppTest2 extends AbstractAppTest {
public void twoUsersSignUp(#Optional Object[][] data) throws InterruptedException {
...
}
}
Now the code of the setUp method does not need to be repeated, and it uses the implementation of the twoUsersSignUp method provided in each of the two subclasses of AbstractAppTest.
You can't just convert a method to a class.
However, you can create new objects or modify existing objects.
Initialize your testData class like this
public class ApptestData{
public WebDriver driver;
public WebDriverWait wait;
public ApptestData() throws Exception {
File firefoxPath = new File(System.getProperty("lmportal.deploy.firefox.path", "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe"));
FirefoxBinary ffox = new FirefoxBinary(firefoxPath);
ffox.setEnvironmentProperty("DISPLAY", ":20");
driver = new FirefoxDriver(ffox, null);
wait = new WebDriverWait(driver, timeoutInSeconds );
Object[][] data = new Object[1][2];
data[0][0] = driver;
data[0][1] = wait;
twoUsersSignUp(data);
return data;
}
}
And then use that object in your test classes
public class Apptest/AppTest2 {
#Test
public void twoUsersSignUp() throws InterruptedException{
AppTestData data = new AppTestData();
//test here
}
}
The kind of refactoring you are looking for does not exists yet, at least on Eclipse.
A workaround to do it manually is explained here
By the way, in Eclipse by pressing ALT SHIFT T you will find all the current available possibilities to refactor your existent code, by extracting methods, classes etc.
I am relatively new to Java, TestNG and Selenium Webdriver (3 weeks) and it seems Im not passing parameters correctly, the way TestNG wants me to.
The test runs perfectly, but then it says it failed for the following reason:
org.testng.TestNGException:
The data provider is trying to pass 2 parameters but the method com.pragmaticqa.tests.AppTest2#twoUsersSignUp takes 1
Here is my code:
public class AppTest2 {
public WebDriver driver;
public WebDriverWait wait;
#DataProvider(name = "dataProvider")
public Object[][] setUp() throws Exception {
File firefoxPath = new File(System.getProperty("lmportal.deploy.firefox.path", "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe"));
FirefoxBinary ffox = new FirefoxBinary(firefoxPath);
ffox.setEnvironmentProperty("DISPLAY", ":20");
driver = new FirefoxDriver(ffox, null);
wait = new WebDriverWait(driver, timeoutInSeconds );
Object[][] data = new Object[1][2];
data[0][0] = driver;
data[0][1] = wait;
twoUsersSignUp(data);
return data;
}
#Parameters({ "data" })
#Test(dataProvider = "dataProvider")
public void twoUsersSignUp(#Optional Object[][] data) throws InterruptedException{
//test here
}
}
You need to declare your test method with the data that you are filling in the dataprovider, so in your case, it should be
public void twoUsersSignUp(WebDriver d, WebDriverWait w).