Saturday, November 13, 2010

Testing sorting feature of an application

All applications display data and allow the user to sort the data on some column. I am sure you would have written or executed test cases to test the sorting feature of your application. There are many strategies to automate such test. In this post I will try to explain a strategy I use widely.

Data is generally displayed in the form of a table (webtable) with each row containing one record. Generally in web applications the sorting feature is given on some or all column of the table. Let’s look at one such website that displays data in this fashion. Navigate to www.vcdq.com


This website as you can see has information on the latest movie releases. It allows you to sort the data on two of the columns, Date and Release. You can sort the data by clicking the respective column header. Both columns can be sorted in ascending and descending order. A small arrow icon is indicating the current sorting order next to the column header text.

My strategy involves the following
a)    Reading all the data of this table into a java ArrayList. Lets call this ExpectedList
b)    Perform the sort on the application by clicking the column header
c)    Read the data from the table again and store it in another ArrayList. Lets call this ActualListAfterSort
d)    Sort the ExpectedList
e)    Compare ExpectedList with ActualListAfterSort and verify that the order of the elements is same.

There is a distinction between the ArrayList that holds primitive datatypes like String or int and the one I use. I use a user defined class to hold the rows of data. Each member element of this class represents one column of the table. The class is defined below.

public class ReleaseInfoTableRecord {
String standard;
Date date;
String format;
String source;
String release;
double imdb;
int disks;
String group;
int ratingAudio;
int ratingVideo;

public ReleaseInfoTableRecord(String standard, Date date, String format,
        String source, String release, double imdb, int disks, String group,
        int ratingAudio, int ratingVideo) {
    super();
    this.standard = standard;
    this.date = date;
    this.format = format;
    this.source = source;
    this.release = release;
    this.imdb = imdb;
    this.disks = disks;
    this.group = group;
    this.ratingAudio = ratingAudio;
    this.ratingVideo = ratingVideo;
}
}

I will insert objects of this class into the ArrayList. An object will represent one row of the table. This is how will insert record within the ArrayList.

ArrayList<ReleaseInfoTableRecord> LatestMovieReleaseDisplayed=new ArrayList<ReleaseInfoTableRecord>();
        
LatestMovieReleaseDisplayed.add(new ReleaseInfoTableRecord(standard, date, format, 
                    source, release, imdb, disks, group, ratingAudio, ratingVideo  ) );

Now in order to sort the data of the ArrayList I would have to define some comparators. I will have to define comparators for all the sort features that I wish to test. For example If the application under test allows sorting the data on ascending and descending order on column Date and I want to test this feature than I need to define two comparators one for ascending and other for descending on date. I will be defining these comparators in the class ReleaseInfoTableRecord.

static final Comparator<ReleaseInfoTableRecord> SORT_DATE_ASCENDING =  new Comparator<ReleaseInfoTableRecord>(){
    public int compare(ReleaseInfoTableRecord o1, ReleaseInfoTableRecord o2) {
        int result = o1.getDate().compareTo(o2.getDate());
        if (o1.getDate().equals(o2.getDate()))
            result =o1.getRelease().compareTo(o2.getRelease())*-1;
        return (result);
    }
};

static final Comparator<ReleaseInfoTableRecord> SORT_DATE_DESCENDING =  new Comparator<ReleaseInfoTableRecord>(){
    public int compare(ReleaseInfoTableRecord o1, ReleaseInfoTableRecord o2) {
        int result = o1.getDate().compareTo(o2.getDate())*-1;
        if (o1.getDate().equals(o2.getDate()))
            result =o1.getRelease().compareTo(o2.getRelease());
        return (result);
    }
};


The hashCode and equals method of the data class must be overridden to make the comparison possible. This overriden methods can be genarated in eclipse by doing right click source-->generate hashcode and equals. You will se this below in the full class code.

If the two records have the same date then the application sorts on the basis of Release name. Note the logic for each comparator when the date is same. This is specific to this application and the application that you are testing may have a different logic. Go thru the application logic carefully before defining the comparators.

Now we define the actual test method that tests the sorting feature. Note that I have read the data into the ArrayList dataAsDisplayedInDefaultView in an earlier step. The code in the while loop is instruction that performs the sorting on the web application i.e clicks the column header link repeatedly till the appropriate arrow icon appears. Your application may involve steps different than this to invoke sort.

@Test
    public void testSortingDateAscending() {            
        int i=0;
        //Click Date column header till the small up arrow is visible next to <Date> column header, 
        //don't get confused by the title of the up arrow image        
        while (false==selenium.isElementPresent("//table//th[2]/a/img[@title='sort descending']")&&i<2){
        selenium.click("link=Date");
        selenium.waitForPageToLoad("30000");
        }        
        
        ArrayList<ReleaseInfoTableRecord> dataAsDisplayedAfterSort=getLatestMovieReleaseDisplayed();
        //make a copy of the arraylist that holds the displayed data 
        ArrayList<ReleaseInfoTableRecord> expectedOrder=dataAsDisplayedInDefaultView;
        //sort the copy on Date Descending, this is how the data is sorted in the default view on this website
        Collections.sort(expectedOrder, ReleaseInfoTableRecord.SORT_DATE_ASCENDING);
        //This will pass only if the elements in both the lists appear in the same order
        org.testng.Assert.assertTrue(dataAsDisplayedAfterSort.equals(expectedOrder));        
    }

Below you can see both the classes in their full glory. ReleaseInfoTableRecord class that will be used to hold the data (record of the table) and SortingTest is the test class.

package test;


import java.util.Comparator;
import java.util.Date;

public class ReleaseInfoTableRecord {
String standard;
Date date;
String format;
String source;
String release;
double imdb;
int disks;
String group;
int ratingAudio;
int ratingVideo;

public ReleaseInfoTableRecord(String standard, Date date, String format,
        String source, String release, double imdb, int disks, String group,
        int ratingAudio, int ratingVideo) {
    super();
    this.standard = standard;
    this.date = date;
    this.format = format;
    this.source = source;
    this.release = release;
    this.imdb = imdb;
    this.disks = disks;
    this.group = group;
    this.ratingAudio = ratingAudio;
    this.ratingVideo = ratingVideo;
}



@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((date == null) ? 0 : date.hashCode());
    result = prime * result + disks;
    result = prime * result + ((format == null) ? 0 : format.hashCode());
    result = prime * result + ((group == null) ? 0 : group.hashCode());
    long temp;
    temp = Double.doubleToLongBits(imdb);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    result = prime * result + ratingAudio;
    result = prime * result + ratingVideo;
    result = prime * result + ((release == null) ? 0 : release.hashCode());
    result = prime * result + ((source == null) ? 0 : source.hashCode());
    result = prime * result + ((standard == null) ? 0 : standard.hashCode());
    return result;
}
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    ReleaseInfoTableRecord other = (ReleaseInfoTableRecord) obj;
    if (date == null) {
        if (other.date != null)
            return false;
    } else if (!date.equals(other.date))
        return false;
    if (disks != other.disks)
        return false;
    if (format == null) {
        if (other.format != null)
            return false;
    } else if (!format.equals(other.format))
        return false;
    if (group == null) {
        if (other.group != null)
            return false;
    } else if (!group.equals(other.group))
        return false;
    if (Double.doubleToLongBits(imdb) != Double.doubleToLongBits(other.imdb))
        return false;
    if (ratingAudio != other.ratingAudio)
        return false;
    if (ratingVideo != other.ratingVideo)
        return false;
    if (release == null) {
        if (other.release != null)
            return false;
    } else if (!release.equals(other.release))
        return false;
    if (source == null) {
        if (other.source != null)
            return false;
    } else if (!source.equals(other.source))
        return false;
    if (standard == null) {
        if (other.standard != null)
            return false;
    } else if (!standard.equals(other.standard))
        return false;
    return true;
}
public String getStandard() {
    return standard;
}
public void setStandard(String standard) {
    this.standard = standard;
}
public Date getDate() {
    return date;
}
public void setDate(Date date) {
    this.date = date;
}
public String getFormat() {
    return format;
}
public void setFormat(String format) {
    this.format = format;
}
public String getSource() {
    return source;
}
public void setSource(String source) {
    this.source = source;
}
public String getRelease() {
    return release;
}
public void setRelease(String release) {
    this.release = release;
}
public double getImdb() {
    return imdb;
}
public void setImdb(double imdb) {
    this.imdb = imdb;
}
public int getDisks() {
    return disks;
}
public void setDisks(int disks) {
    this.disks = disks;
}
public String getGroup() {
    return group;
}
public void setGroup(String group) {
    this.group = group;
}
public int getRatingAudio() {
    return ratingAudio;
}
public void setRatingAudio(int ratingAudio) {
    this.ratingAudio = ratingAudio;
}
public int getRatingVideo() {
    return ratingVideo;
}
public void setRatingVideo(int ratingVideo) {
    this.ratingVideo = ratingVideo;
}

static final Comparator<ReleaseInfoTableRecord> SORT_DATE_ASCENDING =  new Comparator<ReleaseInfoTableRecord>(){
    public int compare(ReleaseInfoTableRecord o1, ReleaseInfoTableRecord o2) {
        int result = o1.getDate().compareTo(o2.getDate());
        if (o1.getDate().equals(o2.getDate()))
            result =o1.getRelease().compareTo(o2.getRelease())*-1;
        return (result);
    }
};

static final Comparator<ReleaseInfoTableRecord> SORT_DATE_DESCENDING =  new Comparator<ReleaseInfoTableRecord>(){
    public int compare(ReleaseInfoTableRecord o1, ReleaseInfoTableRecord o2) {
        int result = o1.getDate().compareTo(o2.getDate())*-1;
        if (o1.getDate().equals(o2.getDate()))
            result =o1.getRelease().compareTo(o2.getRelease());
        return (result);
    }
};


static final Comparator<ReleaseInfoTableRecord> SORT_RELEASE_ASCENDING =  new Comparator<ReleaseInfoTableRecord>(){
    public int compare(ReleaseInfoTableRecord o1, ReleaseInfoTableRecord o2) {
        int result = o1.getRelease().compareTo(o2.getRelease());
        return (result);
    }
};

static final Comparator<ReleaseInfoTableRecord> SORT_RELEASE_DESCENDING =  new Comparator<ReleaseInfoTableRecord>(){
    public int compare(ReleaseInfoTableRecord o1, ReleaseInfoTableRecord o2) {
        int result = o1.getRelease().compareTo(o2.getRelease());
        return (result * -1);
    }
};

}


package test;


import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;

import org.openqa.selenium.server.SeleniumServer;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.thoughtworks.selenium.SeleneseTestCase;

public class SortingTest extends SeleneseTestCase{
    
    ArrayList<ReleaseInfoTableRecord> dataAsDisplayedInDefaultView;

     @BeforeClass
        public void setUp() throws Exception {
            SeleniumServer seleniumserver=new SeleniumServer();
            seleniumserver.boot();
            seleniumserver.start();
            setUp("http://www.vcdq.com", "*firefox");
            selenium.open("/");
            selenium.windowMaximize();
            selenium.windowFocus();
            
            //filter the results to reduce the data-set to manageable levels            selenium.select("filterStandard", "label=SCENE");
            selenium.select("filterTerm3", "label=DVDR");
            selenium.select("filterTerm2", "label=DVD");
            selenium.click("//input[@value='Filter']");
            selenium.waitForPageToLoad("20000");
            dataAsDisplayedInDefaultView=getLatestMovieReleaseDisplayed();
        }    
    
    @Test
    public void testDefaultSorting(){                
        //make a copy of the arraylist that holds the displayed data 
        ArrayList<ReleaseInfoTableRecord> expectedOrder=dataAsDisplayedInDefaultView;
        //sort the copy on Date Descending, this is how the data is sorted in the default view on this website
        Collections.sort(expectedOrder, ReleaseInfoTableRecord.SORT_DATE_DESCENDING);
        //This will pass only if the elements in both the lists appear in the same order
        org.testng.Assert.assertTrue(dataAsDisplayedInDefaultView.equals(expectedOrder));        
    }
    
        
    @Test
    public void testSortingDateAscending() {            
        int i=0;
        //Click Date column header till the small up arrow is visible next to <Date> column header, 
        //don't get confused by the title of the up arrow image
        while (false==selenium.isElementPresent("//table//th[2]/a/img[@title='sort descending']")&&i<2){
        selenium.click("link=Date");
        selenium.waitForPageToLoad("30000");
        }        
        
        ArrayList<ReleaseInfoTableRecord> dataAsDisplayedAfterSort=getLatestMovieReleaseDisplayed();
        //make a copy of the arraylist that holds the displayed data 
        ArrayList<ReleaseInfoTableRecord> expectedOrder=dataAsDisplayedInDefaultView;
        //sort the copy on Date Descending, this is how the data is sorted in the default view on this website
        Collections.sort(expectedOrder, ReleaseInfoTableRecord.SORT_DATE_ASCENDING);
        //This will pass only if the elements in both the lists appear in the same order
        org.testng.Assert.assertTrue(dataAsDisplayedAfterSort.equals(expectedOrder));        
    }
    
    @Test
    public void testSortingReleaseNameAscending(){
        int i=0;
        //Click Date column header till the small up arrow is visible next to <Release> column header, 
        //don't get confused by the title of the up arrow image
        while (false==selenium.isElementPresent("//table//th[6]/a/img[@title='sort descending']")&&i<2){
        //Click Date column header once so that the sort ascending image is visible
        selenium.click("link=Release");
        selenium.waitForPageToLoad("30000");
        i=i+1;
        }
        
        ArrayList<ReleaseInfoTableRecord> dataAsDisplayedAfterSort=getLatestMovieReleaseDisplayed();
        //make a copy of the arraylist that holds the displayed data 
        ArrayList<ReleaseInfoTableRecord> expectedOrder=dataAsDisplayedInDefaultView;
        //sort the copy on Date Descending, this is how the data is sorted in the default view on this website
        Collections.sort(expectedOrder, ReleaseInfoTableRecord.SORT_RELEASE_ASCENDING);
        //This will pass only if the elements in both the lists appear in the same order
        org.testng.Assert.assertTrue(dataAsDisplayedAfterSort.equals(expectedOrder));        
    }
    
    @Test
    public void testSortingReleaseNameDescending(){            
        int i=0;
        //Click Date column header till the small up arrow is visible next to <Release> column header, 
        //don't get confused by the title of the up arrow image        
        while (false==selenium.isElementPresent("//table//th[6]/a/img[@title='sort ascending']")&&i<2) {
        //Click Date column header once so that the sort ascending image is visible
        selenium.click("link=Release");
        selenium.waitForPageToLoad("30000");        
        }
        
        ArrayList<ReleaseInfoTableRecord> dataAsDisplayedAfterSort=getLatestMovieReleaseDisplayed();
        //make a copy of the arraylist that holds the displayed data 
        ArrayList<ReleaseInfoTableRecord> expectedOrder=dataAsDisplayedInDefaultView;
        //sort the copy on Date Descending, this is how the data is sorted in the default view on this website
        Collections.sort(expectedOrder, ReleaseInfoTableRecord.SORT_RELEASE_DESCENDING);
        //This will pass only if the elements in both the lists appear in the same order
        org.testng.Assert.assertTrue(dataAsDisplayedAfterSort.equals(expectedOrder));        
    }
    
    public ArrayList<ReleaseInfoTableRecord> getLatestMovieReleaseDisplayed() {
        ArrayList<ReleaseInfoTableRecord> LatestMovieReleaseDisplayed=new ArrayList<ReleaseInfoTableRecord>();
        
        String standard;
        Date date=null;
        String format;
        String source;
        String release;
        double imdb;
        int disks;
        String group;
        int ratingAudio;
        int ratingVideo;
        
        String rating;
        String imdbCellContent;
        int tableRowCount=selenium.getXpathCount("/descendant::table//tr").intValue();
        
        //read the data from the webtable
        for (int i=1;i<tableRowCount;i++){
            standard=selenium.getText("XPATH=/descendant::table//tr["+i+"]//td[1]");
            DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
            try{
            date=df.parse(selenium.getText("XPATH=/descendant::table//tr["+i+"]//td[2]"));
            }catch (ParseException p){
                System.out.println(p.getMessage());
            }
            
            format=selenium.getText("XPATH=/descendant::table//tr["+i+"]//td[4]");
            source=selenium.getText("XPATH=/descendant::table//tr["+i+"]//td[5]");
            release=selenium.getText("XPATH=/descendant::table//tr["+i+"]//td[6]");
            imdbCellContent=selenium.getText("XPATH=/descendant::table//tr["+i+"]//td[10]");            
            imdb=!(imdbCellContent.equalsIgnoreCase("N/A"))?Double.parseDouble(selenium.getText("XPATH=/descendant::table//tr["+i+"]//td[10]")):0.0;
            disks=Integer.parseInt(selenium.getText("XPATH=/descendant::table//tr["+i+"]//td[11]"));
            group=selenium.getText("XPATH=/descendant::table//tr["+i+"]//td[12]");
            rating=selenium.getText("XPATH=/descendant::table//tr["+i+"]//td[13]");
            ratingVideo=Integer.parseInt(rating.split(" ")[0].split(":")[1]);
            ratingAudio=Integer.parseInt(rating.split(" ")[1].split(":")[1]);
            
            //insert the data as a instances of the class ReleaseInfoTableRecord into the arraylist
            LatestMovieReleaseDisplayed.add(new ReleaseInfoTableRecord(standard, date, format, 
                    source, release, imdb, disks, group, ratingAudio, ratingVideo  ) );
    }
return LatestMovieReleaseDisplayed;
}
    
}

Copy paste these classes into your project and run as testng test to see them in action.

This is the most robust and foolproof strategy I have come across for testing sorting functionality. I use it to test search results, reports etc. You might also want to create test data before invoking the sort i.e create test data items abc, efg, zab or you could just use the existing data in the system.

59 comments:

  1. Mahesh,
    This is exactly what I'm looking for. I'm trying to follow what you did but it looks like the site has changed since you posted this and I can't quite work out some of the details. Can you explain the section where the comment starts:

    //filter the results to reduce the data-set to manageable levels

    I may be able to work out the details with this bit but it would be best if you could update such that your code will work with the site as is.

    This is an excellent post. Well done!

    ReplyDelete
  2. Hi Mahesh,
    I just wanted to know how to handle the Ext-JS pages by using the selenium. This is am trying from couple of days before,my test case is getting failed because of random ID generation in Ext-JS pages. Can you please explain me how to handle this case
    contact me on nagaraja12hebbar@gmail.com

    Regards
    Nagaraj

    ReplyDelete
  3. It seems to be a useful information and I am sure, there will be many out there who will prefer implement automation testing in the same way like you did.

    ReplyDelete
  4. Very informative post thanks for share this with us i highly appreciate you for this information thanks once again for sharing information like this Very informative post Thanks for sharing with you, I appreciate this information thank you again for sharing information like this!.............:)
    Automated System

    ReplyDelete
  5. The application is really good. Liked the way it is conveyed in the post.
    mobile application development services

    ReplyDelete
  6. Thanks a lot for sharing!!!Your input really helped.

    ReplyDelete
  7. This tutorial comes handy to testers while doing automation. Thank you.
    Selenium Automation Testing Framework

    ReplyDelete
  8. The best practice for automation frameworks relies on integrated test management tools with automation tool, which helps to achieve reliability and faster test execution as well as easy maintenance of the automation test scripts.Software Test Automation

    ReplyDelete
  9. Hi, thanks for sharing such an informative blog. I have read your blog and I gathered some needful information from your blog. Keep update your blog. Awaiting for your next update.
    Regards
    Selenium Training in Chennai

    ReplyDelete
  10. Thank you for this great information and I appreciate you to Awesome way to present your thoughts and knowledge.
    I am a beginner and I want to learn more .Keep sharing your knowledge with us.
    Selenium Interview Questions
    Selenium Tutorial
    Selenium Training in Noida

    ReplyDelete
  11. Thanks for the great information in your blog Selenium Training in Chennai

    ReplyDelete
  12. Hi
    Wow... what an informative post for testing automation. The blog post written in a superb way.....CLEARLY DEFINES EVERYTHING WITH A DETAILED VIEW :) cheers!!! Building automation

    ReplyDelete
  13. This is one of the most incredible blogs I've read in a very long time. The amount of information in here is stunning, like you practically wrote the book on the subject. Your blog is great for anyone who wants to understand this subject more. Great stuff; please keep it up!
    selenium automation testing

    ReplyDelete
  14. Learn Selenium WebDriver Online Training By Professional IT Expert.
    Selenium Training in Hyderabad

    ReplyDelete



  15. In that ideas was really good and everyone sharing described to be grate informative give that's you'll give that all content sharing and easy learning explanation.
    SAP SuccessFactors Online Training

    ReplyDelete
  16. Great site for these post and i am seeing the most of contents have useful for my Carrier.Thanks to such a useful information.Any information are commands like to share him.

    digital marketing course in chennai
    hadoop training in chennai

    ReplyDelete
  17. Thank you so much for sharing. it’s useful for me.
    Learn a training in Best Institute & get a 100% placement Assistant................
    Selenium Training in Chennai
    Dot Net Training in Chennai
    Hadoop Training in Chennai

    ReplyDelete

  18. Useful information,don't stop sharing and Please keep updating us..... Thanks

    ReplyDelete

  19. Good blog post conveyed a helpful information.keep updating...
    SEO Company in India

    ReplyDelete
  20. This comment has been removed by the author.

    ReplyDelete
  21. Nice information and thanks for sharing

    automation testing courses online

    ReplyDelete
  22. Really superb information.Thanks for sharing.

    Weblogic Admin Training

    ReplyDelete
  23. Big Thanks for this wonderful read. I enjoyed every little bit of reading and I have bookmarked your website to check out new stuff of your blog a must read blog.


    Selenium Training in Chennai
    Selenium Training
    Selenium Course in Chennai

    ReplyDelete
  24. Thanks for sharing your information. Great efforts put it to find it which is really amazing. It is very useful to know, Definitely will share the same to other forums.
    best openstack training in Chennai | openstack training center in Chennai | openstack certification training in Chennai | openstack course fees in chennai

    ReplyDelete
  25. This is an best post. It is Really very informative concept.I like it and help me to development very well.Thanks alot for this brief explanation and very nice information.Keyword

    ReplyDelete
  26. Thanks for your great and helpful presentation I like your good service. I always appreciate your post. That is very interesting I love reading and I am always searching for informative information like this.iot training institutes in chennai | industrial iot training chennai | iot training center in chennai | best iot training centre in chennai

    ReplyDelete
  27. All the points you described so beautiful. Every time i read your i blog and i am so surprised that how you can write so well.
    Asp.Net Training in Chennai
    Software Testing Institutes in Chennai
    Java Training Institutes in Chennai with 100 Placement
    PHP Certification in Chennai

    ReplyDelete
  28. Pretty article! I found some useful information in your blog, it was awesome to read, thanks for sharing this great content to my vision, keep sharing. Need to learn
    Test Automation Services
    Regression Testing Services
    Functional Testing Services
    Performance Testing Services
    Security Testing Services

    ReplyDelete
  29. Such a great information for blogger i am a professional blogger thanks…

    Softgen Infotech is the Best HADOOP Training located in BTM Layout, Bangalore providing quality training with Realtime Trainers and 100% Job Assistance.

    ReplyDelete
  30. Thanks for Sharing This Article.It is very so much valuable content. I hope these Commenting lists will help to my website
    sailpoint online training

    ReplyDelete
  31. Thanks for sharing such a great information.It is really one of the finest article and more informative too. I want to share some informative data about sap course and sap abap training . Thank you. expecting more articles from you.

    ReplyDelete
  32. The blog is very useful and informative which provides great information and I really loved it.Cisco SD-WAN Training

    ReplyDelete
  33. The blog is very useful and informative checkpoint

    ReplyDelete
  34. Nowadays, id verification service is higher in need. There are numerous id verification methods that anybody can receive on a professional site termed Trust Swiftly, and an agency can use the methods to secure their own web business ideally. By visiting this excellent https://www.trustswiftly.com internet site, you can obtain details of id verification service.

    ReplyDelete

  35. This blog will help to get more ideas. This is very helpful for Software Testing learners. Thank you for sharing this wonderful site. If someone wants to know about Software QA services this is the right place for you Software QA Companies. Visit here

    21 CFR Part 11 Compliance Testing

    HIPAA Validation Services

    Pci Compliance Testing services

    ReplyDelete
  36. The Blog contains the effective and attractive information’s and thanks for the blog.
    JAVA Course in Chennai
    JAVA Course in Bangalore


    ReplyDelete
  37. Thank you for sharing this. Best Automation Anywhere training in Chennai. visit our website for more info: Best Automation Anywhere Training Institute in Chennai

    ReplyDelete
  38. Modern problems demand modern solutions, and if it is ultimately about the growth of your organization, one shouldn't take any chances. A leading conversational intelligent service desk program, Rezolve.ai provides immediate, real-time resolutions to employee issues. Rezolve.ai, an AI-enabled HR ticketing system, reduces 70% of repetitive questions and boosts HR productivity by 35%.

    Click here: AI service desk

    ReplyDelete
  39. To know more about AI automated service desk and help desk with rezolve.ai, click down the link here: : https://bit.ly/3MyfJ5Q

    ReplyDelete
  40. We are master managed service provider and we are also provide professional services and noc services 24*7 and outsourced service.
    infrassist
    join Microsoft Teams Meeting
    noc services for msp
    managed noc services

    ReplyDelete
  41. The website is looking bit flashy and it catches the traffic eyes. layout is beautiful clean and a enjoyable adherent without problems reached interface. Serial Movavi Video Editor

    ReplyDelete
  42. Quite for your liking pronounce. I just stumbled about your blog and desired to publicize that i've in truth enjoyed reading your weblog posts. Any pretension i will be subscribing to your feed and that i hope you call anew soon. big thanks for the beneficial data. thank you! keep rocking. Kaspersky Cracked

    ReplyDelete
  43. Its a cozy delight reading your claim.Its full of aspire i am looking for and i lionize to claim a comment that "The content material of your proclaim is incredible" extremely good accomplish..... Good Night Memorial Day

    ReplyDelete
  44. My Lear Nest Training Academy is one of the best SAP HCM course which is located in Hyderabad KPHB and the training which they provide is very good and they make it easy to learn. They will clear all your doubts as soon as possible. classes will be scheduled on time and trainers are very punctual.

    ReplyDelete
  45. Great blog! Your testing strategy is well thought out and meticulous.
    Also Read: AUTOMATION IN SOFTWARE TESTING: A COURSE FOR THE FUTURE

    ReplyDelete
  46. I just wanted to drop by and say how much I enjoyed reading this blog post. Your writing style is captivating, and your knowledge on the outsourced NOC support services is impressive.

    ReplyDelete
  47. Its Very Use Full Information , For More Information Search Software Testing course Online Training, Thanking You

    ReplyDelete