WebUI.verifyLinksAccessible is not very useful; a Custom Keyword verifyLinkAccesible is proposed

I tried WebUI.verifyLinksAccessible (https://docs.katalon.com/display/KD/[WebUI]+Verify+Links+Accessible) and found it not very useful. I would argue that

  1. WebUI.verifyLinksAccessible does not return boolean value. So that I can not see if the link is accutally accessible or not.
  2. WebUI.verifyLinksAccessible requires List of links. If given 2 or more links as argument, the how can we see which link is accessible and not. I think it is better to give a single link URL and verify its accessibility.

Bearing this in mind, I have developed a CustomeKeywords as follows:

package com.happymigration
import java.net.InetSocketAddress
import java.net.Proxy
import java.net.URL
import java.net.URLConnection
import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import com.kms.katalon.core.annotation.Keyword
import com.kms.katalon.core.checkpoint.Checkpoint
import com.kms.katalon.core.checkpoint.CheckpointFactory
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords
import com.kms.katalon.core.model.FailureHandling
import com.kms.katalon.core.testcase.TestCase
import com.kms.katalon.core.testcase.TestCaseFactory
import com.kms.katalon.core.testdata.TestData
import com.kms.katalon.core.testdata.TestDataFactory
import com.kms.katalon.core.testobject.ObjectRepository
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords
import internal.GlobalVariable as GlobalVariable
import MobileBuiltInKeywords as Mobile
import WSBuiltInKeywords as WS
import WebUiBuiltInKeywords as WebUI
public class UrlUtils {
/**
 * checks if a sinble URL is accesible or not.
 * 
 * @param urlString
 * @return true if it is accesible, otherwise false
 */
@Keyword
boolean verifyUrlAccessible(String urlString) {
  URL url = new URL(urlString)
  HttpURLConnection conn
  // Proxyが指定されていたらProxyを通過するように設定する
  if (GlobalVariable.G_http_proxy_host && GlobalVariable.G_http_proxy_port) {
    Proxy proxy = new Proxy(Proxy.Type.HTTP, 
      new InetSocketAddress(GlobalVariable.G_http_proxy_host,
    Integer.parseInt(GlobalVariable.G_http_proxy_port)));
    conn = (HttpURLConnection) url.openConnection(proxy)
  } else {
    conn = (HttpURLConnection) url.openConnection()
  }
  conn.setRequestMethod("GET")
  conn.setConnectTimeout(10000)
  def result
  // URLに接続して成功するかどうかを試す
  try {
    conn.connect()
    if (conn.responseCode == 200
      || conn.responseCode == 201) {
      // 2xx Success
      result = true
    } else if (conn.responseCode == 301
      || conn.responseCode == 302
      || conn.responseCode == 303
      || conn.responseCode == 307) {
      // 3xx Redirection
      result = true
    } else {
      // 4xx Client Error
      // 5xx Server Error
      result = false
    }
  } catch (IOException e) {
    result = false
  }
  return result
}
}

Provided with this CustomeKeywords.‘com.happymigration.UrlUtils.verifyLinkAccesible’, I developed a TestCase which check all the external links in a Page: the code goes as follows:

WebUI.navigateToUrl(targetURL)

allLinks = WebUI.getAllLinksOnCurrentPage(true, [])
allLinks.each({ def link ->
    if (shouldCheckForAccesibility(link)) {
        //result = WebUI.verifyLinksAccessible(Arrays.asList(link),                       FailureHandling.CONTINUE_ON_FAILURE)
        // WebUI.verifyLinksAccessible is not very useful
        // Rather use CustomeKeyword
        boolean result = CustomKeywords.'com.happymigration.UrlUtils.verifyUrlAccessible'(link)
        WS.comment('Verifying a link to ' + link) // URLがアクセス可能かどうかを調べる
        WS.verifyEqual(true, result)
        /* wait for 0.5 second,  to be gentle for the targeted site */        Thread.sleep(500 )    }
}) 
def shouldCheckForAccesibility(String url) {
    if (!url.startsWith('http://') && !url.startsWith('https://')) return false
    if (url.contains(GlobalVariable.G_Hostname)) return false
    if (url.contains('font-awesome')) return false
    if (url.contains('fonts.googleapis.com')) return false
    if (url.contains('www.facebook.com')) return false
    if (url.contains('twitter.com')) return false
    return true
}

I can perform WS.verifyEqual(expect,actual) using the result boolean value returned by CustomeKeyword. It is very important to report PASSED/FAILED about each links’ accessibility.

2 Likes

I found that Katalon Studio lacks feature of executing JUnit tests over my Java/Grooby codes as CustomeKeyword.

Initially my CustomKeywords.‘com.happymigration.UrlUtils.verifyUrlAccessible’ was just a few lines of code. But soon my CustomKeyword started to grow, become larger and more complexed. I realized that it deserved JUnit tests. I could not find a way how to execuite JUnit in Katalon Studio project. Therefore I created a new Eclipse project where I write Java code for my CustomeKeyword and performed JUnit testing just as I usually do. Then I copied and pasted the finalized Java code into Katalon Studio. — This way saved me. But it is obviously non-efficient.

I am afraid that, in the current Katalon Studio design, Custom Keyword is not regarded as a first-class citizen. It is rather regarded as a supplemental feature which is better than having nothing. I would propose you, Katalon Team, to promote it.

Just I mean, please let me do JUnit testing for my Custom Keywords.

2 Likes

I have created another post https://forum.katalon.com/discussion/5389/want-to-execute-unit-tests-by-junit-for-my-java-groovy-code-as-cutom-keyward?new=1

I would not mind it if this post is closed.

1 Like

Hi kazurayam,

for a new testing project I am now also confronted with having to implement a sophisticated check of the accessibility status of websites. You already mentioned at https://forum.katalon.com/discussion/comment/19610#Comment_19610 that you finally used the Apache HttpClient library for this in your further development. Do you see a way to make this project available to the public? I’m sure that would be of great interest to many others here as well. Many thanks in advance!

Do you see a way to make this project available to the public?

Sorry, I am not keen on this idea.

I reviewed my previous project (named HttpURLVerifier) where I verified URL accessibility in <a href="..."> and <img src="..."> by checking HTTP Response Status Code == 200 or not with Apache HttpClient. I found the source codes are immature, poorly written. I do not like exposing this to public.

And I have studied that the HttpURLVerifier (verification primarily base on HTTP Status) is not very useful. Why? … well, long way to go…

1 Like

Well, I understand that, of course. That is, you would rather advise against using Apache’s HttpClient library for this purpose and recommend a different approach? I am still at the very beginning and would like to check status codes on the one hand. But on the other hand, similar to you, at status 200 (OK) I want also to be able to react to typical error contents like “page not found”.

In addition, in another project, I had already encountered that at least the WebUI.navigateToUrl() method causes problems if the called page loads endlessly (because any external services addressed by the page do not respond etc.). Since navigateToUrl() doesn’t offer a configurable timeout parameter, in such cases it doesn’t throw any error at all that could be caught. Rather, the whole test simply aborts uncontrollably at some point without any report being generated at all. I think this is a bug that I will still report to the Katalon team. But I can’t imagine how I can safely catch such cases in any other way, and whether WebUI.verifyLinksAccessible() could help me with this.

WebUI.navigateToUrl() method causes problems if the called page loads endlessly (because any external services addressed by the page do not respond etc.). Since navigateToUrl() doesn’t offer a configurable timeout parameter, in such cases it doesn’t throw any error at all that could be caught.

I take your point. I understand you want to do this:

String url = "http://this.host/will/never/respond"
WebUI.openBrowser('')
CustomKeywords.'my.HttpURLVeirifer.verifyAccessibility'(    url, 10, FailureHandling.STOP_ON_FAILURE)
WebUI.navigateToUrl(url)
...

However, I would argue that automated test does not worth doing against a never-responding-host. It is too bad to test with the noble WebDriver. When you find the dull host, you should immediately meet the developer and say “Our server is sleeping! Wake him up.”

And my current code base is poorly written, I hesitate exposing it to public. Please understand it.

1 Like

No, that’s not quite true yet, as I was still too imprecise in my description: The case of endless loading occurs with the same URL only once in 20 to 50 attempts and is therefore unfortunately difficult to reproduce. With your code snippet it could probably happen that the line

CustomKeywords.'my.HttpURLVeirifer.verifyAccessibility'(url, 10, FailureHandling.STOP_ON_FAILURE)

will pass without any problems whereas only in the line

WebUI.navigateToUrl(url)

the test will stuck.

Therefore, I would like a way to put the routines for determining the status code in a try block and, if the page does not respond in a reasonable time, to go to the next url or safely terminate the test case within the catch block. But, unfortunately, at least navigateToUrl() won’t throw any exception in these special cases …

So the point is that the test should still work in principle and we want to accept the occasionally occurring answer problems as long as they can’t be solved completely.

Just added the bug report concerning the problem of WebUI.navigateToUrl(url) with endlessly loading webpages.