I am writing a small integration piece to to retrive the testcases from TestCase Management tool in java, in which i have the following scenarios:-
1) I have testcase which is “failed”, that time I am checking whether there is any defect which is already exists in the Defect management tool for the failed testcase using the testcase name , because the testcase name and the defect name are same in our case.
If not I am logging the new defect. This is fine.
2) In another case, I have testcase which is “Passed” at the first time, for that also I am checking the whether there are any duplicate defect is present in the Defect management tool , eventhough I am not going to log any defect.
This I am doing because, I don’t know whether the testcase is “Pass” or “Fail” in the first attempt or not. Hence I am doing this mandatory check , to see whether the duplicate defect exists or not for both “pass” and “fail” testcase.
I know that it is wrong to check the duplicate existence of the defect for the “pass” testcase. But there is no option I have. Is there any way we can ignore calling duplicate existence of the defect method if the testcase is “passed”?
I want your guys opinion on this.
This is the code which i have:-
private int NOT_TESTED = 0;
private int PASSED_1 = 0;
private int PASSED_2 = 0;
private int FAILED =0;
private String testStatus = "pass"; // will be fetched dynamically
private void execute(){
if(testStatus.equalsIgnoreCase("fail")){
//FAILED--;
FAILED = FAILED + 1;
System.out.println("the failed value is:"+FAILED);
}else if(testStatus.equalsIgnoreCase("pass")){// first attempt
PASSED_1 = PASSED_1 + 1;
System.out.println("the Passed_1 value is:"+PASSED_1);
if(PASSED_1 == 1){
System.out.println("Passed in the first attempt, hence no need to create a defect");
}
}else if(testStatus.equalsIgnoreCase("pass") && FAILED ==1){// second attempt
PASSED_2 = PASSED_2+1;
System.out.println("the Passed_2 value is:"+PASSED_2);
if(PASSED_2 ==1){
System.out.println("Passed in the second attempt, create a defect");
// logic to create a new defect
}
}else {
System.out.println("The test not tested");
}
}
This code is not working as it always go to the first pass attempt state, hence please do provide a solution to find if the testcase is passed in the second attempt (FAIL->PASS) so that we can take appropriate action on this.
Thanks in advance.
if the condition (testStatus.equalsIgnoreCase("pass") && FAILED ==1) is true, it means that the condition before it is also true:
if(testStatus.equalsIgnoreCase("pass"))
Since you used if-else, it will go into the first condition and then skip the rest.
Switching between those two will give you the desired result I think.
Related
Ok so, I need to test this method which contains a switch case statement:
#Override
public int delete() {
LOGGER.info("--------------------------------------------------------------------------------------------------\n"
+ "Please select whether you would like to delete the entire order, or an item from the order");
LOGGER.info("DEL ORDER/DEL ITEM");
String action = utils.getString();
action = action.toUpperCase();
switch (action) {
case "DEL ORDER":
LOGGER.info("--------------------------------------------------------------------------------------------------\n"
+ "Please enter the order id of the order you would like to delete:");
Long order_id = utils.getLong();
orderDAO.delete(order_id);
LOGGER.info("------------------------------Order has successfully been deleted!------------------------------");
break;
case "DEL ITEM":
LOGGER.info("--------------------------------------------------------------------------------------------------\n"
+ "Please enter the order id you would like to delete an item from:");
Long order_id2 = utils.getLong();
LOGGER.info("Please enter the item id you would like to delete from the order:");
Long item_id = utils.getLong();
orderDAO.itemDelete(order_id2, item_id);
LOGGER.info("------------------------------Item from order has successfully been deleted!------------------------------");
break;
default:
LOGGER.info("Invalid input, please try again!");
return 0;
}
return 0;
}
but what I've got so far isn't giving me any coverage at all! Not sure where I'm going wrong but it's all in red... I assumed I could split it into two testing methods as they are separate "branches" of the switch statement, so I'm not sure why this isn't working. I know the code itself works as I have tested it with SQL entries.
#Test
public void testDeleteOrder() {
long order_id = 1L;
String action = "DEL ORDER";
Mockito.when(this.utils.getString()).thenReturn(action);
Mockito.when(utils.getLong()).thenReturn(order_id);
Mockito.when(dao.delete(order_id)).thenReturn(1);
// assertEquals(1, this.controller.delete());
//
// Mockito.verify(utils, Mockito.times(1)).getLong();
// Mockito.verify(dao, Mockito.times(1)).delete(order_id);
}
//
// public void testDeleteItem() {
// long order_id2 = 1L;
// long item_id = 1L;
// String action = "DEL ITEM";
// Mockito.when(this.utils.getString()).thenReturn(action);
// Mockito.when(utils.getLong()).thenReturn(order_id2);
// Mockito.when(utils.getLong()).thenReturn(item_id);
// Mockito.when(dao.itemDelete(order_id2, item_id)).thenReturn(1);
////
//// assertEquals(1, this.controller.delete());
////
//// Mockito.verify(utils, Mockito.times(2)).getLong();
//// Mockito.verify(dao, Mockito.times(1)).itemDelete(order_id2, item_id);
// }
#ParameterizedTest
#ValueSource(strings = {"DEL ORDER", "DEL ITEM"})
void testMethod(String action) {
Mockito.when(this.utils.getString()).thenReturn(action);
Mockito.when(utils.getLong()).thenReturn(order_id);
Mockito.when(dao.delete(order_id)).thenReturn(1);
switch (action) {
case "DEL ORDER":
verify(dao).delete(anyLong());
break;
case "DEL ITEM":
verify(dao).itemDelete(anyLong(), anyLong());
break;
default:
verifyNoInteractions(dao);
}
verifyNoMoreInteractions(dao);
}
Testing a method and the actual coverage are the targets defined while implementing it. Following the TDD principles on the best scenarios, tests are created on the same time as the method is being implemented, so that you can pick easily design/dependency problems and avoid them.
In that way the method would be constantly refactored so that the code remains simple and it can be properly tested and write a test class. Going the opposite way on large services / big flows, usually is not easy, as you would end up mocking every single dependency/entity required and miss the actual test purpose.
This means that you would define your actual test coverage, based on the scope and the areas you consider as most harmful.
Sharing some ideas.
Imagine that you have to write a test for the below method :
public int sum(int a, int b) {
return a + b;
}
Things are very simple here, no dependencies(dao,services) and we know what we expect.
The only question that rises, is whether we would need numeric validation etc, but thats again on the actual scope.
So our test would be something like (simpler code, simpler the test) :
assertEquals(5, aBean.sum(2,3));
Getting on your sample again sharing an idea on how you can break it up, based on the implementation by looking on the most important areas:
DAO wiring
Testing against the actual dependency injection, to confirm that bean creation is successful. Of course this is a container matter, so you would need to check this in very specific occasions.
Switch case
Verifying that the switch case is working of course is not required, but verifying that the expected methods are executed in each action is a good point.
DB operation
This is more extreme as it requires external integration either with a mock or a development DataBase. We need to verify that the method does what it says, so we actually need to verify that the sample.entry has been indeed removed from the database.
The last point might be your full coverage, as it would cover both that the actions are getting executed and that the expected result is confirmed.
I would also suggest to take a look on TDD practices and some samples with Junit + Mockito to check the usages of Mockito.when, Mockito.verify, Spies.
I have a simple webtable called branch which has columns id, branchName, BranchLocaction. Ihave to scenarios to add one branch and test if it is correctly added or not. I have the below function which is supposed to give me the latest id before addition and after addition. before addition its invoked properly and gives me the correct row. But afteradding, some times it gives the old id, sometimes correctly new id, sometimes null. Its a definitely wait isssue. I am also calling some customized functions to wait for ajax call/jquery. But still it does not help. Please help me. If you need more detail. PLease let me know
public int getlatestBranchtID() throws InterruptedException
{
int totalnoOfrows = driver.findElements(By.xpath("//table[#class='table table-striped']/tbody/tr")).size();
System.out.println(totalnoOfrows);
if (totalnoOfrows == 0)
{
return Integer.parseInt("0");
}
else{
String latestBranchID= driver.findElements(By.xpath("//table[#class='table table-striped']/tbody/tr/td[1]")).get(totalnoOfrows-1).getText();
System.out.println("latest branch id is" + latestBranchID);
return Integer.parseInt(latestBranchID);
}
}
I currently have an issue in my script where I use a for loop to iterate through an array of elements and check for their existence in the GUI. My issue is the for loop always skips the first entry of the array.
My current script is as follows:
public class GUIFunctionality {
static Properties config = Data.getProperties("config");
static int Pass = 0;
static Screen s = new Screen();
#Test(priority = 0)
public static void loginGUI() {
WebDriver driver = AutomationWebDriver.getWebDriver("firefox", config.getProperty("url"));
// Test all GUI elements on login screen.
String[] login_elements = { "loginbutton.png", "logintitle.png", "smalllogo.png", "remembermechecked.png",
"signupbutton.png", "signuptitle.png", "changelanguage.png" };
ArrayList<String> passed = new ArrayList<String>();
ArrayList<String> failed = new ArrayList<String>();
for (String base : login_elements) {
String file = String.format("imagerepo/config/%s", base);
if (s.exists(file) != null) {
System.out.println(file + " has been successfully found.");
passed.add(file);
Pass++;
} else {
System.out.println(file + " has not been found.");
failed.add(file);
}
}
This script completely ignores "loginbutton.png", almost as though it never existed in the script at all. I'm really stumped as to why. Here is the console output:
imagerepo/config/logintitle.png has been successfully found.
imagerepo/config/smalllogo.png has been successfully found.
imagerepo/config/remembermechecked.png has been successfully found.
imagerepo/config/signupbutton.png has been successfully found.
imagerepo/config/signuptitle.png has been successfully found.
imagerepo/config/changelanguage.png has been successfully found.
Found elements: [imagerepo/config/logintitle.png, imagerepo/config/smalllogo.png, imagerepo/config/remembermechecked.png, imagerepo/config/signupbutton.png, imagerepo/config/signuptitle.png, imagerepo/config/changelanguage.png]
Missing elements: []
I'm wondering what I need to alter so the first entry of the String[] login_elements is included in the for loop. What's also interesting is that adding one more entry to the String[] login_elements will completely fix it.
Making this minor change: (nobutton.png is an image that exists within the repository, but not on the page under test)
String[] login_elements = { "nobutton.png", "loginbutton.png", "logintitle.png", "smalllogo.png",
"remembermechecked.png", "signupbutton.png", "signuptitle.png", "changelanguage.png" };
This one change will now print this to the console:
imagerepo/config/nobutton.png has not been found.
imagerepo/config/loginbutton.png has been successfully found.
imagerepo/config/logintitle.png has been successfully found.
imagerepo/config/smalllogo.png has been successfully found.
imagerepo/config/remembermechecked.png has been successfully found.
imagerepo/config/signupbutton.png has been successfully found.
imagerepo/config/signuptitle.png has been successfully found.
imagerepo/config/changelanguage.png has been successfully found.
Found elements: [imagerepo/config/loginbutton.png, imagerepo/config/logintitle.png, imagerepo/config/smalllogo.png, imagerepo/config/remembermechecked.png, imagerepo/config/signupbutton.png, imagerepo/config/signuptitle.png, imagerepo/config/changelanguage.png]
Missing elements: [imagerepo/config/nobutton.png]
This console output includes every entry within that array. Deleting "nobutton.png", from the array will bring us back to our original issue.
So what the heck is going on? The only thing I can possibly think of is a minimum number of strings in an array to include the first entry, but that just seems downright silly.
Edit: s.exists(String) is an instance of the Sikuli screen using the exists function to check for the existance of elements on the page. I really do not think this has anything to do with the error. I also could be completely wrong about this. I've learned most of the Sikuli library through trial-and-error (time-crunch around release dates is a horrible thing), so my ignorance on "why" is pretty high, which is why I'm here.
Edit: Remember, adding one more entry to the array completely fixes the problem.
Edit: Added the instance of s. The line WebDriver driver = AutomationWebDriver.getWebDriver("firefox", config.getProperty("url")); is an instance of a Selenium WebDriver I use to start the instance of WebDriver which I have to use alongside Sikuli because our web application is fubar (6 years of legacy code).
Another Edit: Source code for Region.exists() method and documentation.
Source Code
Documentation
This question has been answered. #Berger and #Andy Thomas have also provided some insight into what happens with the loop:
I think I have found the source code. exists uses a while loop based on a timeout value, among other things, so a subsequent call with the same parameter, could well return another result, see : https://github.com/RaiMan/SikuliX-2014/blob/master/API/src/main/java/org/sikuli/script/Region.java - #Berger
I see from another Sikuli source file that the default autoWaitTimeout is 63 seconds, making the race condition easy to observe. Two important lessons from this question are: 1) A default case is frequently useful, especially if it's not expected to occur -- and 2) If you want a single return value, make a single call. - #Andy Thomas
You don't have a default case. You're using an if-elseif rather than an if-else.
for (String base : login_elements) {
String file = String.format("imagerepo/config/%s", base);
if (s.exists(file) != null) {
...
} else if (s.exists(file) == null) {
...
}
}
Your second condition includes a second call to s.exists(file). If neither branch is entered, the value returned must be changing between calls.
You could handle this by adding a default case. An easy way would be to eliminate the second condition.
for (String base : login_elements) {
String file = String.format("imagerepo/config/%s", base);
if (s.exists(file) != null) {
...
} else {
...
}
}
A debugger can help you find problems like this. If you set a breakpoint on the first condition, you'd see that the first file is being considered by the loop.
I believe the Java code should be:
String[] login_elements = {
"loginbutton.png",
"logintitle.png",
"smalllogo.png",
"remembermechecked.png",
"signupbutton.png",
"signuptitle.png",
"changelanguage.png"
};
ArrayList<String> passed = new ArrayList<String>();
ArrayList<String> failed = new ArrayList<String>();
for (String base : login_elements) {
String file = String.format("imagerepo/config/%s", base);
File s = new File(file);
if (s.exists()) {
System.out.println(file + " has been successfully found.");
passed.add(file);
}
else {
System.out.println(file + " has not been found.");
failed.add(file);
}
}
System.out.println("Found elements: " + passed);
System.out.println("Missing elements: " + failed);
This is because you are not facing all possibilities:
if (s.exists(file) != null) {
System.out.println(file + " has been successfully found.");
passed.add(file);
} else {
System.out.println(file + " has not been found.");
failed.add(file);
}
Will throw an error with your same code...
public void returnRental(Customer cust){
Rental toDelete = null; //Rental to be removed from list.
LinkedList<Video> toReturn = null; //List of videos to be added to inventory.
//Find appropriate rental according to customer name.
for(int i = 0; i < rentals.size(); i++){
if(cust.getName() == rentals.get(i).getRentee().getName()){
toReturn = rentals.get(i).getRented();
toDelete = rentals.get(i);
}
}
here is the snippet of code that is giving me problems. I've debugged it in eclipse quite a bit which ended up just confusing me more. It hits the if, and passes the condition. But once it gets to assigning values to "toReturn" it assigns it an empty list with size 0. Where as I check my rentals Linked list and the correct value are there, but for some reason it is not getting assigned to my variables correctly :( The same happens to "toDelete" but this isn't a list, it is one instance of my class Rental. (The linked list is a list of rentals, which contains a linked list of videos)
No errors are thrown...
Its a little difficult to explain, if you need more information please let me know and i'll clarify.
I'm at a loss, possibly because I'm not iterating through my linked list correctly?
Replace
if (cust.getName() == rentals.get(i).getRentee().getName()){
by
if (cust.getName().equals(rentals.get(i).getRentee().getName())){
You can't compare strings with == (except if your algorithm can ensure this is the same instance, which is almost never the case).
But the missing equals is not the only bug. It may be inside getRented() or elsewhere (you don't show what you do with toReturn and toDelete, so it's not clear if you don't have problems here).
Now, to go on chasing your bugs, you should either
debug, and put a breakpoint in your loop to check the state of rentals.get(i) and the execution at this point
if you can't debug, put a lot of System.println, so that you know what you have...
I've upvoted dystroy's answer because incorrect string comparison is always wrong.
But because that would fail differently (customer names not matching rentee names), I'm wondering if your issue is really caused by either of the following:
a problem in getRented(); or
cust having a null name on call, which would match a Rentee with a null name.
Possibly, your if condition is being hit more than once. First of all, check if this is actually happening. If so, check your logic and determine if you want to stop at the first occurence or at the last (this case seems to be the latter).
If you want to stop at the first occurence, break the iteration:
for(int i = 0; i < rentals.size(); i++){
if(cust.getName() == rentals.get(i).getRentee().getName()){
toReturn = rentals.get(i).getRented();
toDelete = rentals.get(i);
break;
}
}
for(int i = 0; i < rentals.size(); i++){
if(cust.getName().equals( rentals.get(i).getRentee().getName())){
toReturn.addAll(rentals.get(i).getRented());
//assumming it returns the list of Video object
toDelete = rentals.get(i);
}
}
This is my class reponsible for new item entries, and from the start it has been a complete nightmare, I can't seem to resolve the issues I am facing which are:
setStock(float) in Item cannot be applied to ()
Item entry:
private void writeItemRecord()
{
// Check to see if we can connect to database table
if ( DataBaseHandler.makeConnectionToitemDB() == -1)
{
JOptionPane.showMessageDialog (frame, "Unable to connect to database table (Item)");
}
else // Ok, so first read data from the text fields
{
// Read data from form and store data
String Itemname = ItemnameTxtField.getText();
String Itemcode = ItemcodeTxtField.getText();
String Description = DescriptionTxtField.getText();
String Unitprice = UnitpriceTxtField.getText();
String Style = StyleTxtField.getText();
String Finish = FinishTxtField.getText();
String Stock = StockTxtField.getText();
// Convert priceStr to a float
Float fvar = Float.valueOf(Unitprice);
float price = fvar.floatValue();
Float svar = Float.valueOf(Stock);
float stock = svar.floatValue();
// Create a Item oject
Item Item = new Item();
// Set the attributes for the Item object
Item.setItemname (Itemname);
Item.setItemcode (Itemcode);
Item.setDescription (Description);
Item.setUnitprice (price);
Item.setStock(stock);
Item.setStyle(Style);
Item.setFinish(Finish);
// Write Item record. Method writeToItemTable() returns
// 0 of OK writing record, -1 if there is a problem. I store
// the returned value in a variable called error.
int error = DataBaseHandler.writeToItemTable(Item.getItemname(),
Item.getItemcode(),
Item.getDescription(),
Item.getUnitprice(),
Item.setStock(),
Item.setStyle(Style),
Item.setFinish(Finish),
Item.setSuppliercode(Suppliercode),
Item.setSuppliername(Suppliername),
Item.setAddress(Address)
);
// Check if there is a problem writing the record, in
// which case error will contain -1
if (error == -1)
{
JOptionPane.showMessageDialog (frame, "Problem writing record to Item Table");
}
// Clear the form - actual method is coded below
clearForm();
// Close database connection. Report an error message
// if there is a problem.
if ( DataBaseHandler.closeConnection() == -1 )
{
JOptionPane.showMessageDialog (frame, "Problem closing data base conection");
}
}
} // End
Any help is much appreciated!
And item extracts:
public void setStock(float StockIn)
{
Stock = StockIn;
}
public float getStock()
{
return Stock;
}
For starters, adhere to Java naming conventions. Nothing except class/interface names is allowed to use CamelCase. Use lowerCamelCase. As for your "problem", you wrote
Item.setStock(),
so obviously it's giving you the error. It is also giving you the exact line number of the error, something that would obviously have helped us to diagnose your problem.
Solution: use Item.getStock() (i suppose, it's hard to tell). Calling Item.setStock at that position (as an argument to a method call) is meaningless anyway, given that setStock is a void method.
Java compiler errors come with a line number - pay attention to it. This is your problem:
Item.setStock()
setStock() requires a parameter, you are trying to call it without one. Perhaps you meant getStock()? And I suspect that all the calls to set methods in the parameter list to writeToItemTable are also wrong, as those set methods will have void as return value, so you can't use them that way.
The setStock method looks like this:
public void setStock(float StockIn)
To call it, you need to pass a float as an argument. Somewhere in your code, you call the method, like this:
Item.setStock(),
The method needs to be called with the float argument, but instead it's called with none, hence you see a compilation error.
In this code:
int error = DataBaseHandler.writeToItemTable(Item.getItemname(),
Item.getItemcode(),
Item.getDescription(),
Item.getUnitprice(),
// Right here --> Item.setStock(),
Item.setStyle(Style),
Item.setFinish(Finish),
Item.setSuppliercode(Suppliercode),
Item.setSuppliername(Suppliername),
Item.setAddress(Address)
);
Notice that you're calling Item.setStock(), Item.setStyle(Style), etc. instead of Item.getStock(), Item.getStyle(), etc. This is probably the source of your problem - you're trying to call the setStock() method with no arguments, hence the error.
Hope this helps!
This line
// Create a Item oject
Item Item = new Item();
Is problematic. Not only is it bad style in Java to use uppercase names for variables, this particular instance results in a compile error. Also, you're calling setStock without a parameter. You need to fix that as well.
Here is your error:
int error = DataBaseHandler.writeToItemTable(Item.getItemname(),
Item.getItemcode(),
Item.getDescription(),
Item.getUnitprice(),
Item.setStock(), // <<< here! should be getStock()
Item.setStyle(Style),
Item.setFinish(Finish),
Item.setSuppliercode(Suppliercode),
Item.setSuppliername(Suppliername),
Item.setAddress(Address));
But again... consider naming/coding conventions.