Skip to main content
Start running your tests on the latest iOS minor versions on BrowserStack App Automate. Check out our documentation!

Log contextual information using console annotations

Use console annotators to customize logs that you want to send to BrowserStack from within the test script for debugging or tracking.

In this guide, you will learn:

Introduction

Your test script contains contextual information related to the test, such as description of the test, start and end of scenarios, or any other data that you may want to print on the console for debugging and tracking. Using console annotations, you can add configurations in your tests that will log this information on BrowserStack. These logs are available on the App Automate Dashboard along with the other text logs. These logs provide a way for you to quickly search and go to a specific section of the test and troubleshoot any failed tests.

After you run a test that includes console annotations, you can view these logs with the annotations on the App Automate Dashboard as seen in the following example:

Console Annotation

Send logs to BrowserStack using JavascriptExecutor

You can send annotations to BrowserStack from within the test script using the the annotate action implemented through the JavascriptExecutor as shown in the following snippets:

JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript("browserstack_executor: {\"action\": \"annotate\", \"arguments\": {\"data\": \"<any string>\", \"level\": \"<info/warn/debug/error>\"}}");
driver.executeScript('browserstack_executor: {"action": "annotate", "arguments": {"data":"<any string>","level": "<info/warn/debug/error>"}}');
((IJavaScriptExecutor)driver).ExecuteScript("browserstack_executor: {\"action\": \"annotate\", \"arguments\": {\"data\":\"<any string>\", \"level\": \" <info/warn/debug/error> \"}}");
$web_driver->executeScript('browserstack_executor: {"action": "annotate", "arguments": {"data":"<any string>", "reason": "<info/warn/debug/error>"}}' );
driver.execute_script('browserstack_executor: {"action": "annotate", "arguments": {"data":"<any string>", "level": "<info/warn/debug/error>"}}')
caps["javascriptEnabled"] = "true" #Additionally, include this capability for JavaScript executors to work

driver.execute_script('browserstack_executor: {"action": "annotate", "arguments": {"data":"<any string>", "reason": "<info/warn/debug/error>"}}')

The arguments passed in the JavaScript method for setting the status and the corresponding reason for the test are data and level.

  • data accepts a value in string data-type.
  • level accepts the standard log severity levels, namely info , debug , warn, and error . This argument is optional with the default value of info.

Searching and Filtering

After your test script has sent console annotations to BrowserStack, you can find all the annotations pushed to the logs in the Text Logs tab on the App Automate dashboard.

You can either search with the logged text in the searchbar or directly navigate to the section of test execution where you want to troubleshoot. This search feature is particularly helpful when your test sessions run for a long duration.

Console Annotation searching

You can also filter these annotated logs based on the severity levels and customize the selection based on your logging patterns.

Console Annotation filtering

Sample code

The following code snippets show the annotation that is sent to BrowserStack when a product is added to the cart.

package android;

import java.net.URL;
import java.util.List;
import java.net.MalformedURLException;

import io.appium.java_client.MobileBy;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.remote.DesiredCapabilities;


public class BrowserStackSample {

  public static void main(String[] args) throws MalformedURLException, InterruptedException {
    
      DesiredCapabilities caps = new DesiredCapabilities();

      caps.setCapability("app", "bs://84061b61cfcf6166bcd3468065b2707c0db3baa9");
      caps.setCapability("device", "Google Pixel 3");
      caps.setCapability("os_version", "9.0");

        AndroidDriver<AndroidElement> driver = new AndroidDriver<AndroidElement>(
            new URL("https://YOUR_USERNAME:YOUR_ACCESS_KEY@hub-cloud.browserstack.com/wd/hub"), caps);

        JavascriptExecutor jse = (JavascriptExecutor)driver;
        // logging start of test session at BrowserStack
        jse.executeScript("browserstack_executor: {\"action\": \"annotate\", \"arguments\": {\"data\": \"Scenario : Search in Wiki\", \"level\": \"info\"}}");

        AndroidElement searchElement = (AndroidElement) new WebDriverWait(driver, 30).until(
            ExpectedConditions.elementToBeClickable(
                MobileBy.AccessibilityId("Search Wikipedia")));
        searchElement.click();
    AndroidElement insertTextElement = (AndroidElement) new WebDriverWait(driver, 30).until(
             ExpectedConditions.elementToBeClickable(
                 MobileBy.id("org.wikipedia.alpha:id/search_src_text")));
        insertTextElement.sendKeys("BrowserStack");
        Thread.sleep(5000);
        List<AndroidElement> allProductsName = driver.findElementsByClassName(
            "android.widget.TextView");
        
        // logging variable for debugging purpose
        jse.executeScript("browserstack_executor: {\"action\": \"annotate\", \"arguments\": {\"data\": \"number of items = " +allProductsName.size() + " \", \"level\": \"debug\"}}");

    // Setting the status of test as 'passed' or 'failed' based on the condition: if results are found for the search
    if (allProductsName.size() > 0) {
      jse.executeScript("browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": {\"status\": \"passed\", \"reason\": \"Results found!\"}}");
      // logging the scenario completion
      jse.executeScript("browserstack_executor: {\"action\": \"annotate\", \"arguments\": {\"data\":\"Scenario : Search in Wiki successful\", \"level\": \"info\"}}");
    }
    else {
      jse.executeScript("browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": {\"status\":\"failed\", \"reason\": \"Results not found\"}}");
      // logging the scenario completion
      jse.executeScript("browserstack_executor: {\"action\": \"annotate\", \"arguments\": {\"data\":\"Scenario : Search in Wiki failed\", \"level\": \"error\"}}");

    }

        driver.quit();
    
  }

}
let wd = require('wd');
let assert = require('assert');
let asserters = wd.asserters;

desiredCaps = {
  'app' : 'bs://c700ce60cf13ae8ed97705a55b8e022f13c5827c',
  'device' : 'Google Pixel 3',
  'os_version' : '9.0',
};

driver = wd.promiseRemote("https://YOUR_USERNAME:YOUR_ACCESS_KEY@hub-cloud.browserstack.com/wd/hub");

driver.init(desiredCaps)
  .then(function () {
    driver.execute('browserstack_executor: {"action": "annotate", "arguments": {"data":"Scenario : Search in wiki","level": "info"}}');
    return driver.waitForElementByAccessibilityId(
      'Search Wikipedia', asserters.isDisplayed 
      && asserters.isEnabled, 30000);
  })
  .then(function (searchElement) {
    return searchElement.click();
  })
  .then(function () {
    return driver.waitForElementById(
      'org.wikipedia.alpha:id/search_src_text', asserters.isDisplayed 
      && asserters.isEnabled, 30000);
  })
  .then(function (searchInput) {
    return searchInput.sendKeys("BrowserStack");
  })
  .then(function () {
    return driver.elementsByClassName('android.widget.TextView');    
  })
  .then(function (search_results) {
    driver.execute('browserstack_executor: {"action": "annotate", "arguments": {"data":"number of items = '+ search_results.length + '","level": "debug"}}');
    // Setting the status of test as 'passed' or 'failed' based on the condition if results are found for the search
    if(search_results.length > 0){
      // logging the scenario completion
      driver.execute('browserstack_executor: {"action": "annotate", "arguments": {"data":"Scenario : Search in Wiki successful","level": "info"}}');
      return driver.execute('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"passed","reason": "Results found!"}}');
    } else {
      // logging the scenario completion
      driver.execute('browserstack_executor: {"action": "annotate", "arguments": {"data":"Scenario : Search in Wiki failed","level": "error"}}');
      driver.execute('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed","reason": "No results available!"}}');
    
     }
  })
  .fin(function() { 
    return driver.quit(); 
  })
  .done();
using System;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Android;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.UI;
using System.Collections.Generic;
using OpenQA.Selenium;

namespace csharp_appium_first_test_browserstack
{
    class Program
    {
        static void Main(string[] args)
        {
            AppiumOptions caps = new AppiumOptions();

            // Set your BrowserStack access credentials
            caps.AddAdditionalCapability("browserstack.user", "YOUR_USERNAME");
            caps.AddAdditionalCapability("browserstack.key", "YOUR_ACCESS_KEY");

            // Set URL of the application under test
            caps.AddAdditionalCapability("app", "bs://2960f620a6aedc02b419670f9c55b36c516fbc37");

            // Specify device and os_version
            caps.AddAdditionalCapability("device", "Google Pixel 3");
            caps.AddAdditionalCapability("os_version", "9.0");

            // Specify the platform name
            caps.PlatformName = "Android";

            // Set other BrowserStack capabilities
            caps.AddAdditionalCapability("project", "First CSharp project");
            caps.AddAdditionalCapability("build", "CSharp Android");
            caps.AddAdditionalCapability("name", "first_test");

                    

            // Initialize the remote Webdriver using BrowserStack remote URL
            // and desired capabilities defined above
            AndroidDriver<AndroidElement> driver = new AndroidDriver<AndroidElement>(
                    new Uri("http://hub-cloud.browserstack.com/wd/hub"), caps);

            // logging start of test session at BrowserStack
            ((IJavaScriptExecutor)driver).ExecuteScript("browserstack_executor: {\"action\": \"annotate\", \"arguments\": {\"data\":\"Scenario : Search in Wiki\", \"level\": \"info\"}}");

            // Test case for the BrowserStack sample Android app. 
            // If you have uploaded your app, update the test case here.
            AndroidElement searchElement = (AndroidElement)new WebDriverWait(
                driver, TimeSpan.FromSeconds(30)).Until(
                SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(
                    MobileBy.AccessibilityId("Search Wikipedia"))
            );
            searchElement.Click();
            AndroidElement insertTextElement = (AndroidElement)new WebDriverWait(
                driver, TimeSpan.FromSeconds(30)).Until(
                SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(
                    MobileBy.Id("org.wikipedia.alpha:id/search_src_text"))
            );
            insertTextElement.SendKeys("BrowserStack");
            System.Threading.Thread.Sleep(5000);

            IReadOnlyList<AndroidElement> allTextViewElements =
                driver.FindElementsByClassName("android.widget.TextView");
            // logging variable for debugging purpose
            ((IJavaScriptExecutor)driver).ExecuteScript("browserstack_executor: {\"action\": \"annotate\", \"arguments\": {\"data\":\"number of items= "+ allTextViewElements.Count + "\", \"level\": \"debug\"}}");

            if ((allTextViewElements.Count > 0))
            {
                ((IJavaScriptExecutor)driver).ExecuteScript("browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": {\"status\":\"passed\", \"reason\": \" Results found! \"}}");
                // logging the scenario completion
                ((IJavaScriptExecutor)driver).ExecuteScript("browserstack_executor: {\"action\": \"annotate\", \"arguments\": {\"data\":\"Scenario : Search in Wiki successful\", \"level\": \"info\"}}");

            }
            else
            {
                ((IJavaScriptExecutor)driver).ExecuteScript("browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": {\"status\":\"failed\", \"reason\": \" Results not found!\"}}");
                // logging the scenario completion
                ((IJavaScriptExecutor)driver).ExecuteScript("browserstack_executor: {\"action\": \"annotate\", \"arguments\": {\"data\":\"Scenario : Search in Wiki failed\", \"level\": \"info\"}}");
            }


            // Invoke driver.quit() after the test is done to indicate that the test is completed.
            driver.Quit();
        }
    }
}
<?php
  require_once('vendor/autoload.php');
    use Facebook\WebDriver\Remote\DesiredCapabilities;
    use Facebook\WebDriver\Remote\RemoteWebDriver;
    use Facebook\WebDriver\WebDriverBy;

    $caps = array(
        "app" => "bs://c700ce60cf13ae8ed97705a55b8e022f13c5827c",
        "device" => "Google Pixel 3",
        "name" => "Bstack-[Php] Sample Test",
        "build" => "Bstack-[Php] Sample Build"
    );

    $driver = RemoteWebDriver::create("https://YOUR_USERNAME:YOUR_ACCESS_KEY@hub-cloud.browserstack.com/wd/hub", $caps);

    # logging start of test session at BrowserStack
    $driver->executeScript('browserstack_executor: {"action": "annotate", "arguments": {"data":"Scenario : Search in wiki","level": "info"}}');
  
    $driver->getTitle();
    # logging variable for debugging purpose
    $driver->executeScript('browserstack_executor: {"action": "annotate", "arguments": {"data":"title  = '+ $driver->getTitle() + '","level": "debug"}}');


  if ($driver->getTitle() == "Wikipedia"){
      # Setting the status of test as 'passed' or 'failed' based on the condition; if title of the web page matches 'Wikipedia'
      $driver->executeScript('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"passed", "reason": "Title matched!"}}' );
      # logging completion of scenario
      $driver->executeScript('browserstack_executor: {"action": "annotate", "arguments": {"data":"Scenario : Search in wiki successful","level": "info"}}');

  }  else {
      $driver->executeScript('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed", "reason": "Title not matched!"}}');
      # logging completion of scenario
      $driver->executeScript('browserstack_executor: {"action": "annotate", "arguments": {"data":"Scenario : Search in wiki failed","level": "error"}}');

  }

  $driver->quit();
?>
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

desired_cap = {
   
    "app" : "bs://84061b61cfcf6166bcd3468065b2707c0db3baa9",
    "device" : "Google Pixel 3",
    "os_version" : "9.0",
}

driver = webdriver.Remote(
    command_executor="https://YOUR_USERNAME:YOUR_ACCESS_KEY@hub-cloud.browserstack.com/wd/hub", 
    desired_capabilities=desired_cap
)

# logging start of test session at BrowserStack
driver.execute_script('browserstack_executor: {"action": "annotate", "arguments": {"data":"Scenario : Search in wiki","level": "info"}}');

search_element = WebDriverWait(driver, 30).until(
    EC.element_to_be_clickable((MobileBy.ACCESSIBILITY_ID, "Search Wikipedia"))
)
search_element.click()
search_input = WebDriverWait(driver, 30).until(
    EC.element_to_be_clickable((MobileBy.ID, "org.wikipedia.alpha:id/search_src_text"))
)
search_input.send_keys("BrowserStack")
time.sleep(5)

# Setting the status of test as 'passed' or 'failed' based on the condition if results are found for the search
search_results = driver.find_elements_by_class_name("android.widget.TextView")
# Adding annotation to the log for debugging and tracking
driver.execute_script('browserstack_executor: {"action": "annotate", "arguments": {"data":"title  = '+ str(len(search_results)) + '","level": "debug"}}');

if (len(search_results) > 0):
    # logging completion of scenario
    driver.execute_script('browserstack_executor: {"action": "annotate", "arguments": {"data":"Scenario : Search in wiki successful","level": "info"}}');
    driver.execute_script('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"passed", "reason": "Results found!"}}');
else:
	driver.execute_script('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed", "reason": "No results found"}}')
driver.quit()
require 'rubygems'
require 'appium_lib'


caps = {}
caps['app'] = 'bs://84061b61cfcf6166bcd3468065b2707c0db3baa9'
caps['device'] = 'Google Pixel 3'
caps['os_version'] = '9.0'
caps['platformName'] = 'android'
caps['javascriptEnabled'] = 'true' #include this capability for JavaScript executors to work


appium_driver = Appium::Driver.new({
    'caps' => caps,
    'appium_lib' => {
        :server_url => "https://YOUR_USERNAME:YOUR_ACCESS_KEY@hub-cloud.browserstack.com/wd/hub"
    }}, true)
driver = appium_driver.start_driver

wait = Selenium::WebDriver::Wait.new(:timeout => 30)
wait.until { driver.find_element(:accessibility_id, "Search Wikipedia").displayed? }
element = driver.find_element(:accessibility_id, "Search Wikipedia")
element.click

wait.until { driver.find_element(:id, "org.wikipedia.alpha:id/search_src_text").displayed? }
search_box = driver.find_element(:id, "org.wikipedia.alpha:id/search_src_text")
search_box.send_keys("BrowserStack")
sleep 5
# logging start of scenario
driver.execute_script('browserstack_executor: {"action": "annotate", "arguments": {"data":"Scenario 1: BrowserStack search successful", "reason": "info"}}')


# Setting the status of test as 'passed' or 'failed' based on the condition if results are found for the search

results = driver.find_elements(:class, "android.widget.TextView")
# logging variable for debugging purpose
driver.execute_script('browserstack_executor: {"action": "annotate", "arguments": {"data":"number of items = '+ results.count.to_s  + '","level": "debug"}}');

if results.count > 0
    driver.execute_script('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"passed", "reason": "Results found"}}')
    # logging completion of scenario
    driver.execute_script('browserstack_executor: {"action": "annotate", "arguments": {"data":"Scenario 1: BrowserStack search successful", "reason": "info"}}')


else
    driver.execute_script('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed", "reason": "No results found"}}')
    # logging completion of scenario
    driver.execute_script('browserstack_executor: {"action": "annotate", "arguments": {"data":"Scenario 1: BrowserStack search successful", "reason": "info"}}')


end

driver.quit

We're sorry to hear that. Please share your feedback so we can do better

Contact our Support team for immediate help while we work on improving our docs.

We're continuously improving our docs. We'd love to know what you liked






Thank you for your valuable feedback

Is this page helping you?

Yes
No

We're sorry to hear that. Please share your feedback so we can do better

Contact our Support team for immediate help while we work on improving our docs.

We're continuously improving our docs. We'd love to know what you liked






Thank you for your valuable feedback!

Talk to an Expert
Talk to an Expert