Home > Back-end >  Passing a Callable as parameter to a method and use its return value as parameter for that same meth
Passing a Callable as parameter to a method and use its return value as parameter for that same meth

Time:10-14

I have written a method that takes in a Callable and an array of arbitrary length of Strings that I use to time the execution time of the Callable and then write the results to a database:

public static <T> T logTimes(Callable<T> callable, String actionToTest, String... testData) throws Exception {
        LocalDateTime before = null;
        T call = null;
        try {
            before = LocalDateTime.now();
            call = callable.call();
            logToDocument(before, LocalDateTime.now(), actionToTest, testData);
        } catch (TimeoutException ex) {
            logToDocument(before, LocalDateTime.now(), actionToTest, testData);
        }
        return call;
    }

This works fine, but I have now run into a situation where I need to pass the return value of the Callable as a parameter to the same method:

public static String loadedPageName(WebDriver driver, int seconds) throws Exception {
        String originPage = pageName(driver);
        By loadingBar = By.xpath("//div[contains(@class, 'progress')]");
        WebDriverWait w = new WebDriverWait(driver, seconds);
        Function<WebDriver, Boolean> pageFinishedLoading = wd -> wd.findElements(loadingBar).size() == 0;
        AtomicReference<String> dest = new AtomicReference<>();
        try {
            return ExtentTestManager.logTimes(()-> {
                w.until(ExpectedConditions.presenceOfAllElementsLocatedBy(loadingBar));
                w.until(pageFinishedLoading);
                dest.set(driver.findElement(By.tagName("body")).getAttribute("page-name"));
                return dest;
            }, REDIRECT, ORIGIN, originPage, DESTINATION, dest.get()).get();
        } catch (TimeoutException ex) {
            ExtentTestManager.reporterLog("Timeout after waiting ".concat(String.valueOf(seconds)).concat(" seconds for a page to load"));
            ExtentTestManager.logToDocument(LocalDateTime.now(), seconds, REDIRECT, ORIGIN, originPage, DESTINATION, "timeout");
            return null;
        }
    }

This method waits until a page has loaded and returns the name of the loaded page. I want to use that return value as a parameter in the same invocation of ExtentTestManager.logTimes(Callable<T> callable, String actionToTest, String... testData) as the Callable<T> callable that is one of its parameters.

As it is now, loadedPageName(WebDriver driver, int seconds) returns the page name as expected, but logTimes writes null to the database for the result of callable.

Is there a way to achieve this?

CodePudding user response:

Your code in logTimes is equivalent to:

    try {
        before = LocalDateTime.now();
        call = callable.call();
        
    } catch (TimeoutException ex) {
        // do nothing with the exception
    }
    logToDocument(before, LocalDateTime.now(), actionToTest, testData);

Maybe you want to do something with the TimeoutException? Also the calling code in loadedPageName will never encounter a TimeoutException since it is already caught (and ignored) in logTimes.

EDIT: you state "logTimes writes null to the database for the result of callable." I don't understand, logTimes is not writing the result of the callable anywhere, but only returns it.

Maybe you could achieve what I think you want with this:

AtomicReference<String> dest = new AtomicReference<>();
    try {
        return ExtentTestManager.logTimes(()-> {
            w.until(ExpectedConditions.presenceOfAllElementsLocatedBy(loadingBar));
            w.until(pageFinishedLoading);
            dest.set(driver.findElement(By.tagName("body")).getAttribute("page-name"));
            return dest.get();
        }, REDIRECT, ORIGIN, originPage, DESTINATION, dest.get());

I see a problem with the last testData value though: dest.get(). This will not be filled with a value yet when it is evaluated. Probably that's your issue: you are passing the value of the empty AtomicReference in as testData to display.

EDIT: For example:

public static <T> T logTimes(Callable<T> callable, String actionToTest, String... testData) throws Exception {
    LocalDateTime before = LocalDateTime.now();
    T call = callable.call();
    List<String> allTestData = new ArrayList<String>(Arrays.asList(testData));
    allTestData.add(String.valueOf(call));
    logToDocument(before, LocalDateTime.now(), actionToTest, allTestData.toArray(new String[0]));        
    return call;
}
  • Related