At Qxf2 we use BrowserStack to run our automated checks against different browsers. BrowserStack is a cloud-based, cross-browser, testing tool that takes away the pain of maintaining a physical lab and saves us a lot of time.
Why this post?
BrowserStack is a great tool to execute your automated tests. However BrowserStack is not a good tool to report the test results. At our clients, we usually execute our tests on BrowserStack and then report our automated test results to a test case management tool like TestRail or rely on the CI server as the test reporting tool. BrowserStack has useful debug artifacts that we want to share with whatever test reporting system that we integrate with. We especially find the BrowserStack screenshot URLs and the BrowserStack URL for the video replay to be helpful in investigating and reporting failures. We created a BrowserStack library using Python and BrowserStack’s API to help us share these BrowserStack artifacts across our automation framework. We wanted to share it with the testing community.
Overview
We will run a test similar to what we ran in our previous post on BrowserStack. If you need more details on BrowserStack set up and access key please refer to the previous post. We will take one screenshot during the test. BrowserStack saves the screenshot and stores a video recording of the test. We will write a library that will help us access these artifacts and print them out in our test’s log.
Note 1: BrowserStack screenshots are available on Amazon’s S3 for 90 days.
Note 2: BrowserStack’s video recording of your test run is available for 30 days.
So if you are working in a highly risk conscious industry with the chance of being audited, you may want to store these artifacts somewhere else.
A step by step guide
Here are the six steps we will perform:
1. Authenticate
2. Get replay url
3. Get latest screenshot
4. Putting it all together
5. Example usage
6. Running the test
You can use REST API to access information about your tests like build, sessions, session logs etc. We will use Python requests module to achieve this.
Step1. Authenticate
Use your BrowserStack username and access key for authentication
self.auth = ('USERNAME','ACCESSKEY') |
Step2. Get replay url
The replay URL is of form: /builds/$build_id/session/$session_id/. To get the replay URL you need the build id and session id. Let us write methods to get the build id as well as the active session id.
def get_build_id(self): "Get the build ID" self.build_url = self.browserstack_url + "builds.json" builds = requests.get(self.build_url, auth=self.auth).json() build_id = builds[0]['automation_build']['hashed_id'] return build_id def get_sessions(self): "Get a JSON object with all the sessions" build_id = self.get_build_id() sessions= requests.get(self.browserstack_url + 'builds/%s/sessions.json'%build_id, auth=self.auth).json() return sessions def get_active_session_id(self): "Return the session ID of the first active session" session_id = None sessions = self.get_sessions() for session in sessions: #Get session id of the first session with status = running if session['automation_session']['status']=='running': session_id = session['automation_session']['hashed_id'] break return session_id def get_session_url(self,session_id): "Get the video URL from build and session details. Needs to be called after session is completed" build_id = self.get_build_id() self.build_session_url = self.browserstack_url + "builds/"+build_id+"/sessions/"+session_id build_session_details = requests.get(self.build_session_url, auth=self.auth).json() #Get the video url from session details video_url = build_session_details[u'automation_session'][u'video_url'] session_url= video_url.encode("utf-8") return session_url |
Step3. Get latest screenshot
This step is a bit of a hack. There is no direct API call to get a list of screenshots saved by BrowserStack. There is no way to explicitly name the image BrowserStack saves on Amazon’s S3. To get past this, we end up parsing the session logs and find the latest screenshot. Then in our test, we can explicitly name and store the screenshot URL.
def get_session_logs(self): "Return the session log in text format" build_id = self.get_build_id() session_id = self.get_active_session_id() session_log = requests.get(self.browserstack_url + 'builds/%s/sessions/%s/logs'%(build_id,session_id),auth=self.auth).text return session_log def get_latest_screenshot_url(self): "Get the URL of the latest screenshot" session_log = self.get_session_logs() #Process the text to locate the URL of the last screenshot screenshot_request = session_log.split('screenshot {}')[-1] response_result = screenshot_request.split('REQUEST')[0] image_url = response_result.split('https://')[-1] image_url = image_url.split('.png')[0] screenshot_url = 'https://' + image_url + '.png' return screenshot_url |
Step4. Putting it all together Library
This is how our library looks.
""" Qxf2 BrowserStack library to interact with BrowserStack's artifacts. For now, this is useful for: a) Obtaining the session URL b) Obtaining URLs of screenshots """ import os,requests class BrowserStack_Library(): "BrowserStack library to interact with BrowserStack artifacts" def __init__(self,credentials_file=None): "Constructor for the BrowserStack library" self.browserstack_url = "https://www.browserstack.com/automate/" self.auth = ('USERNAME','ACCESS_KEY') def get_build_id(self): "Get the build ID" self.build_url = self.browserstack_url + "builds.json" builds = requests.get(self.build_url, auth=self.auth).json() build_id = builds[0]['automation_build']['hashed_id'] return build_id def get_sessions(self): "Get a JSON object with all the sessions" build_id = self.get_build_id() sessions= requests.get(self.browserstack_url + 'builds/%s/sessions.json'%build_id, auth=self.auth).json() return sessions def get_active_session_id(self): "Return the session ID of the first active session" session_id = None sessions = self.get_sessions() for session in sessions: #Get session id of the first session with status = running if session['automation_session']['status']=='running': session_id = session['automation_session']['hashed_id'] break return session_id def get_session_url(self,session_id): "Get the video URL from build and session details. Needs to be called after session is completed" build_id = self.get_build_id() self.build_session_url = self.browserstack_url + "builds/"+build_id+"/sessions/"+session_id build_session_details = requests.get(self.build_session_url, auth=self.auth).json() #Get the video url from session details video_url = build_session_details[u'automation_session'][u'video_url'] session_url= video_url.encode("utf-8") return session_url def get_session_logs(self): "Return the session log in text format" build_id = self.get_build_id() session_id = self.get_active_session_id() session_log = requests.get(self.browserstack_url + 'builds/%s/sessions/%s/logs'%(build_id,session_id),auth=self.auth).text return session_log def get_latest_screenshot_url(self): "Get the URL of the latest screenshot" session_log = self.get_session_logs() #Process the text to locate the URL of the last screenshot screenshot_request = session_log.split('screenshot {}')[-1] response_result = screenshot_request.split('REQUEST')[0] image_url = response_result.split('https://')[-1] image_url = image_url.split('.png')[0] screenshot_url = 'https://' + image_url + '.png' return screenshot_url |
Step5. Example usage
We are going to execute a Selenium test that visits http://www.chess.com/, asserts the title page and then clicks on the Sign up button and then take a screenshot. We will get and print the BrowserStack video replay URL and screenshot URL using the BrowserStack Library we just created.
import unittest, time from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from BrowserStack_Library import BrowserStack_Library class SeleniumOnBrowserStack(unittest.TestCase): "Example class written to run Selenium tests on BrowserStack" def setUp(self): desired_cap = {'platform': 'Windows', 'browserName': 'Firefox', 'browser_version':'65', 'browserstack.debug': 'true' } self.driver = webdriver.Remote(command_executor='http://USERNAME:[email protected]:80/wd/hub',desired_capabilities=desired_cap) self.browserstack_obj = BrowserStack_Library() def test_chess(self): "An example test: Visit chess.com and click on sign up link" # Go to the URL self.driver.get("http://www.chess.com") # Assert that the Home Page has title "Chess.com - Play Chess Online - Free Games" self.assertIn("Chess.com - Play Chess Online - Free Games", self.driver.title) # Identify the xpath for Play Now button which will take you to the sign up page elem = self.driver.find_element_by_xpath("//a[@title='Play Now']") elem.click() self.driver.save_screenshot("test_chess.png") # Print the title print self.driver.title # Get the Browserstack Screenshot url print "BrowserStack Screenshot url :",self.browserstack_obj.get_latest_screenshot_url() # Get the Browserstack active session id active_session_id = self.browserstack_obj.get_active_session_id() print "BrowserStack session id :",active_session_id # Complete the session self.driver.quit() # Get the Browserstack Session/Video url print "BrowserStack Session url :",self.browserstack_obj.get_session_url(active_session_id) if __name__ == '__main__': unittest.main() |
Step6. Run the Test
You can run the test script the normal way you do. We run it via the command prompt.
We’ll leave you with a screenshot of how we end up hyperlinking these artifacts when reporting to TestRail.
We plan to write a post (within the next 6 months) showing you how to take screenshots automatically, numbers them intelligently, integrate screenshot naming with BrowserStack and then hyperlinking the artifacts to TestRail. If you are in a hurry to get this information, please post a comment below and we will directly share code with you.
I am a dedicated quality assurance professional with a true passion for ensuring product quality and driving efficient testing processes. Throughout my career, I have gained extensive expertise in various testing domains, showcasing my versatility in testing diverse applications such as CRM, Web, Mobile, Database, and Machine Learning-based applications. What sets me apart is my ability to develop robust test scripts, ensure comprehensive test coverage, and efficiently report defects. With experience in managing teams and leading testing-related activities, I foster collaboration and drive efficiency within projects. Proficient in tools like Selenium, Appium, Mechanize, Requests, Postman, Runscope, Gatling, Locust, Jenkins, CircleCI, Docker, and Grafana, I stay up-to-date with the latest advancements in the field to deliver exceptional software products. Outside of work, I find joy and inspiration in sports, maintaining a balanced lifestyle.
Hi Avinash,
I have used your code to get the session url from Browserstack. I am facing issues in getting the correct session_url. It prints the session_url, but it is not correct. The link just downloads a file which can’t be viewed. The session_url varies from the video_url on the site.
Hi,
The URL is the BrowserStack URL which would download the video link. You can try opening that file using VLC media player or any other player and can see the video of the test run.
Hi ,
do you have the code for java with the same functionality
Hi Raj,
We do not have Java code for this functionality.
Thanks,
Nilaya