3 Replies Latest reply on Feb 8, 2011 2:07 AM by Tim Evers

    Tracing broken links

    Hussain Mohammed Ashruf Newbie

      Hello there,

       

      I am using JsfUnit to test my application; I am interested to know, if there is a way to trace broken command links, command buttons in my application. A sample should be good.

       

      Thanks in advance

        • 1. Tracing broken links
          Stan Silvert Master

          I'm not sure if I understand what you are trying to do.  If you click a broken link you will get a FailingHttpStatusCodeException.  You can catch the exception and call getStatusCode() to see if you got a 404 error.

           

          http://htmlunit.sourceforge.net/apidocs/com/gargoylesoftware/htmlunit/FailingHttpStatusCodeException.html

           

          Stan

          • 2. Re: Tracing broken links
            Hussain Mohammed Ashruf Newbie

            Hi Stan, actually I am looking for a way to trace and report broken command links (or say a test case which discovers and loops thru the component Ids, find their type, if it is commandlink/button, try client.click(componet id) it to check if it is broken, meaning the link is not yet to binded to an action), is it possible to do it using JsfUnit.

             

            Thanks in advance

            • 3. Re: Tracing broken links
              Tim Evers Master

              I think you need to think about what you are asking for.

               

              For instance lets use the example of a simple form.

               

              User name: [input]

              Password [input]

               

              LOGIN [button]

               

              So, there are many scenarios here.

               

              First, If the input's are set to required = true and there is client side validation to do that then... clicking on the button without filling in the inputs will not do anything. So effectively you have not tested anything.

               

              Second, Let's assume the button is bound to the action #{LoginSeamBean.login}. You click the button and something happens. Did the right thing happen? What good is the button if it does something but it does the *WRONG* thing. So you end up on an error page when you click the button. Is this actually testing anything? NO.

               

              Third. Let's assume the button is not bound. What will happen when you click the button? Well, that depends doesn't it. If the EL expression is invalid then the page wouldn't have rendered in the first place. So you'll end up on the JSF Error page. IF you are not using an EL expression and have just put an outcome in the action param then nothing will prove that your button works or not unless you have some testable condition that determines if you ended up on the right page based on the outcome(action param) of your button.

               

              The simple solution to this is write proper tests.

               

              Writing generic "test every button works" sounds great, but at the end of the day it doesn't really work.

               

              There are some very very good ways to write JSFUnit tests that make testing your application extremely easy.

               

              First. For every page in your application you will need to write a driver. A driver is a very simple java class that knows how to use each button/link/input/etc on a page.

               

              The contents of a driver may look something like this

               

                  @Override
                  public boolean isDisplayed() {
                      return super.isDisplayed(PAGE);
                  }
              
                  public int getNumberOfResults() {
                      return getTableRowCount(RESULTS_TABLE);
                  }
              
                  public int getNumberOfLockedResults() {
                      return getTableRowCount(RESULTS_TABLE2);
                  }
              
                  public void clickSearch() {
                      click(SEARCH_BUTTON);
                  }
              
                  public void clickClear() {
                      click(CLEAR_BUTTON);
                  }
              

               

              Now when writing tests you don't need to know about the ids of components because the driver takes care of that for you. When you make a change to a page you update the driver and the tests that are affected will break at compile time. *NICE*

               

              Taking this further you can modularise things that lots of tests need. For instance I have a module that logs me into the system for each test. Instead of each test having to get a LoginPageDriver and set the username and password and click the button I can just call JSFUnitLoginHelper.login("myusername", "mypassword", session) and that will take care of the login for me.

               

              So now your tests actually become tests and not masses of client.getComponentById('inputPassword').setValue("myPassword") instead all you'll see in your test is loginPageDriver.setPassword("myPassword").

               

              Also your drivers can be made to know what to expect when a button is clicked and make sure that the expected results were returned. Or if it navigates you to another page your page driver for that page will return false for the isDisplayed() method and that means your button failed somewhere.

               

              I cannot stress enough how much a good, well thought out test structure will help you create tests that *ACTUALLY* give you confidence in the system. With my tests I KNOW for sure that I can login, I know I can get to my search screens and do searches. I know I can create users all verified by my JSFUnit tests.

               

              Here is a simple test for me that goes through from just after login (that get called in the super class) and goes through all the menu options and data entry to navigate to the user search screen, search for a user and verify that results were returned, then click add new user and create a user.

              This test is a pretty old one and my newer tests are probly a bit more elegant but this will give you an idea.

               

               

              public void createUser(String loginId, String firstName, String surname) {
                      IconBarPageDriver iconDriver = getPageDriver(IconBarPageDriver.class);
                      assertTrue("Icon Bar is not visible", iconDriver.isDisplayed());
                      iconDriver.clickHomeIcon();
                      CertificateHomePageDriver certHomePageDriver = 
                          getPageDriver(CertificateHomePageDriver.class);
                      assertTrue("The home page was not displayed", certHomePageDriver.isDisplayed());
                      SideMenuPageDriver menuDriver = getPageDriver(SideMenuPageDriver.class);
                      assertTrue("The side menu was not displayed", menuDriver.isDisplayed());
              
                      log.debug("createUser(): navigate to User Search page.");
                      menuDriver.clickUserSearch();
                      templatepage = getPageDriver(UserTemplatePageDriver.class);
                      searchPage = getPageDriver(UserSearchPageDriver.class);
                      assertTrue("User Search page was not displayed.", searchPage.isDisplayed());
              
                      log.debug("Search for system user");
                      searchPage.setLoginId("SYSTEM");
                      searchPage.clickSearch();
                      assertTrue("No results returned from search.", searchPage.getNumberOfResults() > 0);
              
                      log.debug("createUser(): click create new user link");
                      searchPage.clickAddNewUserLink();
                      maintenancepage = getPageDriver(UserDetailsMaintenancePageDriver.class);
                      assertTrue("User Maintenance page (edit mode) was not displayed.", maintenancepage.isDisplayed());
              //        String name = "UserTestFirstname:" + DateFormatUtils.formatDate(dateSvc.getCurrentDateTime(), DateFormatUtils.ISO_FULL_DATETIME_FORMAT);
                      maintenancepage.setLoginId(loginId);
                      maintenancepage.setSelectOneListValue("rank", 4);
                      maintenancepage.setSelectOneListValue("title", 0);
                      maintenancepage.setSelectOneListValue("location", 0);
                      maintenancepage.setSelectOneListValue("district", 0);
                      maintenancepage.setGivenName(firstName);
                      maintenancepage.setSurname(surname);
                      maintenancepage.setPosition("A POSITION");
                      maintenancepage.clickSave();
                      templatepage.clickExit();
                      assertTrue(
                          "Did not return to search page after exiting create user page.",
                          searchPage.isDisplayed());
                      iconDriver.clickHomeIcon();
                      assertTrue(
                          "The home page was not displayed", 
                          certHomePageDriver.isDisplayed());
                  }