Closed NurlanMirovich closed 3 months ago
There is still one more issue with the custom formatted log's / once the logger configurations are added there is error from the BS
@1114204
@nakula @raunakpilani @kalamcs @punitx Could you please take a look at it when have chance ?
Throwing all BS logs my way
@NurlanMirovich We are checking into the issue, and we will get back with an update soon.
@karanshah-browserstack Thank you !
Hi @karanshah-browserstack have this issue been fixed yet
Hi @NurlanMirovich we're looking into the issue, please give us some time to fix this
@NurlanMirovich This issue is fixed in the latest version of BrowserStack SDK 1.19.23
. Can you please upgrade browserstack-sdk
python package to this version and check once?
Hi @sriteja777 @samarsault @karanshah-browserstack I have updated my requirements to
And i test in local and pipeline, but this is still not wokring, i will include my pytest logs configurations so that you can reproduce
Here is my pytest.ini file
Here is my log files configuration
This module contains shared fixtures, steps, and hooks.
"""
import json
import os
from pytest_bdd import given, parsers, then, when
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from data.test_data import ENROLLMENT_BASE_URL
import logging
import pytest
class ColorFormatter(logging.Formatter):
GREEN = "\033[92m"
LIGHT_RED = "\033[91;1m"
RED = "\033[91m"
YELLOW = "\033[93m"
RESET = "\033[0m"
FORMATS = {
logging.DEBUG: LIGHT_RED + "%(message)s" + RESET,
logging.INFO: GREEN + "%(message)s" + RESET,
logging.WARNING: YELLOW + "%(levelname)s: %(message)s" + RESET,
logging.ERROR: RED + "%(levelname)s: %(message)s" + RESET,
logging.CRITICAL: RED + "%(levelname)s: %(message)s" + RESET,
}
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
number_of_scenarios = []
@pytest.hookimpl
def pytest_bdd_before_scenario(scenario):
number_of_scenarios.append(scenario.name)
logging.info(f"[Scenario Name] - {scenario.name}")
@pytest.hookimpl
def pytest_bdd_after_scenario():
logging.info(f"[Executed scenarios] - {number_of_scenarios}")
@pytest.hookimpl
def pytest_bdd_before_step(step):
logging.info(f"[Step name] - {step.name}")
@pytest.fixture(scope="session", autouse=True)
def setup_logging():
root_logger = logging.getLogger()
root_logger.setLevel(logging.INFO)
console_handler = logging.StreamHandler()
console_handler.setFormatter(ColorFormatter())
root_logger.addHandler(console_handler)
@pytest.fixture
def config(scope='session'):
# Read the file
with open('config.json') as config_file:
config = json.load(config_file)
# Accept values are acceptable
assert config['browser'] in ['firefox', 'chrome', 'headless firefox', 'headless chrome']
assert config['platform'] in ['desktop', 'mobile', 'ios', 'android']
assert isinstance(config['timeout'], int)
assert config['timeout'] > 0
# Return config so it can be used
return config
# This fixture will run once for each test case
@pytest.fixture
def driver(config):
global driver
driver = None
if config['platform'] == 'desktop':
if config["browser"] == "chrome":
options = webdriver.ChromeOptions()
options.add_argument("window-position=-1000,0")
options.set_capability('goog:loggingPrefs', {'browser': 'ALL'})
options.add_experimental_option("detach", True) # keep the browser open after the test run
prefs = {
'autofill.profile_enabled': False
}
options.add_experimental_option('prefs', prefs)
if config["headless_mode"] is True:
options.add_argument("--headless")
driver = webdriver.Chrome(options)
driver.maximize_window()
elif config["browser"] == "firefox":
options = webdriver.FirefoxOptions()
if config["headless_mode"] is True:
options.headless = True
driver = webdriver.Firefox(options)
elif config["browser"] == "edge":
options = webdriver.EdgeOptions()
options.use_chromium = True
if config["headless_mode"] is True:
options.headless = True
driver = webdriver.Edge(options)
elif config["browser"] == "safari":
options = webdriver.SafariOptions()
if config["headless_mode"] is True:
options.headless = True
driver = webdriver.Safari(options)
if config['platform'] == 'mobile':
if config["browser"] == "chrome":
options = webdriver.ChromeOptions()
options.add_argument("window-position=753,92")
options.add_argument("--window-size=414,896") # dimensions of the Iphone XR
options.set_capability('goog:loggingPrefs', {'browser': 'ALL'})
options.add_experimental_option("detach", True)
prefs = {
'autofill.profile_enabled': False
}
options.add_experimental_option('prefs', prefs)
options.add_argument('--disable-notifications')
options.add_argument("--disable-infobars")
options.add_argument("--disable-extensions")
if config["headless_mode"] is True:
options.add_argument("--headless")
driver = webdriver.Chrome(options)
else:
raise Exception(f'Browser "{config["browser"]}" is not supported in local mode')
yield driver
driver.quit()
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item):
pytest_html = item.config.pluginmanager.getplugin("html")
outcome = yield
report = outcome.get_result()
extra = getattr(report, "extra", [])
if report.when == "call":
# always add url to report
extra.append(pytest_html.extras.url(driver.current_url))
xfail = hasattr(report, "wasxfail")
if (report.skipped and xfail) or (report.failed and not xfail):
report_directory = os.path.dirname(item.config.option.htmlpath)
file_name = report.nodeid.replace("::", "_") + ".png"
destination_file = os.path.join(report_directory, file_name)
driver.save_screenshot(destination_file)
if file_name:
html = '<div><img src="%s" alt="screenshot" style="width:300px;height=200px"' \
'onclick="window.open(this.src)" align="right"/></div>' % file_name
# only add additional html on failure
extra.append(pytest_html.extras.html(html))
report.extra = extra
@pytest.fixture
def credentials():
with open('credentials.json') as config_file:
return json.load(config_file)
@given(parsers.parse('the {end_point} page is displayed'), target_fixture="driver")
def navigate_to_page(driver, end_point):
driver.get(ENROLLMENT_BASE_URL + end_point)
wait = WebDriverWait(driver, 30)
wait.until(expected_conditions.url_contains(end_point))
all_elements = By.TAG_NAME, "html"
wait.until(expected_conditions.visibility_of_all_elements_located(all_elements))
return driver
@NurlanMirovich If i understand correctly, the issue you are facing is that you are seeing debug logs from BrowserStack SDK in your Github Actions and also locally even though you have not enabled debug logs. Is my understanding correct?
If so, can you please check these things?
log_level: INFO
to pytest.ini
?logLevel: info
in browserstack.yml
?disableAutoCaptureLogs: true
in browserstack.yml
?Can you please check with above things?
I have tried reproducing the issue with your pytest.ini and log formatter, but wasn't able to reproduce the issue. In my case, I didn't get any debug logs from BrowserStack SDK when I just set as log_level: INFO
in pytest.ini
Thank you @sriteja777 this is partially worked, BUT i have 19 tests in the actions and for some reason it runs only one and drops the execution, i will add the screenshots of the run please let me know
Visit https://observability.browserstack.com/builds/v01rvvlw5m7t0ndnhzft7spsigams1rz5frw6sef to view build report, insights, and many more debugging information all at one place! 16:51:16 [browserstack_sdk.init][INFO] - Handling session close 16:51:16 [browserstack_sdk.init][INFO] - All done! Error: Process completed with exit code 3.
Here is my pytest ini
And BR yaml
# Set BrowserStack Credentials
# =============================
# Add your BrowserStack userName and accessKey here or set BROWSERSTACK_USERNAME and
# BROWSERSTACK_ACCESS_KEY as env variables
userName: ${BROWSERSTACK_USERNAME}
accessKey: ${BROWSERSTACK_ACCESS_KEY}
# ======================
# BrowserStack Reporting
# ======================
# The following capabilities are used to set up reporting on BrowserStack:
# Set 'projectName' to the name of your project. Example, Marketing Website
projectName: python-automation
# Set `buildName` as the name of the job / testsuite being run
buildName: Automation Local run
#sessionName: ${SCENARIO}
# `buildIdentifier` is a unique id to differentiate every execution that gets appended to
# buildName. Choose your buildIdentifier format from the available expressions:
# ${BUILD_NUMBER} (Default): Generates an incremental counter with every execution
# ${DATE_TIME}: Generates a Timestamp with every execution. Eg. 05-Nov-19:30
# Read more about buildIdentifiers here -> https://www.browserstack.com/docs/automate/selenium/organize-tests
buildIdentifier: '#${BUILD_NUMBER}. ${DATE_TIME}' # Supports strings along with either/both ${expression}
# Set `framework` of your test suite. Example, `testng`, `cucumber`, `cucumber-testng`
# This property is needed to send test context to BrowserStack (test name, status)
framework: pytest
# =======================================
# Platforms (Browsers / Devices to test)
# =======================================
# Platforms object contains all the browser / device combinations you want to test on.
# Entire list available here -> (https://www.browserstack.com/list-of-browsers-and-platforms/automate)
platforms:
- os: OS X
osVersion: Big Sur
browserName: Chrome
browserVersion: latest
# =======================
# Parallels per Platform
# =======================
# The number of parallel threads to be used for each platform set.
# BrowserStack's SDK runner will select the best strategy based on the configured value
#
# Example 1 - If you have configured 3 platforms and set `parallelsPerPlatform` as 2, a total of 6 (2 * 3) parallel threads will be used on BrowserStack
#
# Example 2 - If you have configured 1 platform and set `parallelsPerPlatform` as 5, a total of 5 (1 * 5) parallel threads will be used on BrowserStack
parallelsPerPlatform: 1
idleTimeout: 180
# ==========================================
# BrowserStack Local
# (For localhost, staging/private websites)
# ==========================================
# Set browserStackLocal to true if your website under test is not accessible publicly over the internet
# Learn more about how BrowserStack Local works here -> https://www.browserstack.com/docs/automate/selenium/local-testing-introduction
browserstackLocal: false # <boolean> (Default false)
#browserStackLocalOptions:
# - localIdentifier: browserstack_local_identifier
testObservability: true
# Options to be passed to BrowserStack local in-case of advanced configurations
# localIdentifier: # <string> (Default: null) Needed if you need to run multiple instances of local.
# forceLocal: true # <boolean> (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel.
# Entire list of arguments available here -> https://www.browserstack.com/docs/automate/selenium/manage-incoming-connections
# ===================
# Debugging features
# ===================
debug: false # <boolean> # Set to true if you need screenshots for every selenium command ran
networkLogs: true # <boolean> Set to true to enable HAR logs capturing
consoleLogs: errors # <string> Remote browser's console debug levels to be printed (Default: errors)
logLevel: info
disableAutoCaptureLogs : true
# Available options are `disable`, `errors`, `warnings`, `info`, `verbose` (Default: errors)```
Here is another errors from the BS logs
```selenium.common.exceptions.WebDriverException: Message: The property '#/alwaysMatch/bstack:options' contains additional properties ["disableAutoCaptureLogs"] outside of the schema when none are allowed in the payload.
self = <FixtureRequest for <Function test_user_see_transaction_details>>
argname = 'driver'
def getfixturevalue(self, argname: str) -> Any:
"""Dynamically run a named fixture function.
Declaring fixtures via function argument is recommended where possible.
But if you can only decide whether to use another fixture at test
setup time, you may use this function to retrieve it inside a fixture
or test function body.
This method can be used during the test setup phase or the test run
phase, but during the test teardown phase a fixture's value may not
be available.
:param argname:
The fixture name.
:raises pytest.FixtureLookupError:
If the given fixture could not be found.
"""
> fixturedef = self._get_active_fixturedef(argname)
.venv/lib/python3.12/site-packages/_pytest/fixtures.py:585:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv/lib/python3.12/site-packages/_pytest/fixtures.py:607: in _get_active_fixturedef
self._compute_fixture_value(fixturedef)
.venv/lib/python3.12/site-packages/_pytest/fixtures.py:693: in _compute_fixture_value
fixturedef.execute(request=subrequest)
.venv/lib/python3.12/site-packages/_pytest/fixtures.py:1069: in execute
result = ihook.pytest_fixture_setup(fixturedef=self, request=request)
.venv/lib/python3.12/site-packages/pluggy/_hooks.py:501: in __call__
return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
.venv/lib/python3.12/site-packages/pluggy/_manager.py:119: in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
.venv/lib/python3.12/site-packages/_pytest/fixtures.py:1123: in pytest_fixture_setup
result = call_fixture_func(fixturefunc, request, kwargs)
.venv/lib/python3.12/site-packages/_pytest/fixtures.py:895: in call_fixture_func
fixture_result = next(generator)
tests/step_defs/conftest.py:100: in driver
driver = webdriver.Chrome(options)
.venv/lib/python3.12/site-packages/selenium/webdriver/chrome/webdriver.py:45: in __init__
super().__init__(
.venv/lib/python3.12/site-packages/selenium/webdriver/chromium/webdriver.py:56: in __init__
super().__init__(
.venv/lib/python3.12/site-packages/pytest_browserstackplugin/plugin.py:827: in bstack1ll111l1_opy_
bstack1ll1l1l1l_opy_(self, command_executor=command_executor,
.venv/lib/python3.12/site-packages/browserstack_sdk/__init__.py:1186: in bstack1ll111l1_opy_
bstack1ll1l1l1l_opy_(self, command_executor=command_executor,
.venv/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py:208: in __init__
self.start_session(capabilities)
.venv/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py:292: in start_session
response = self.execute(Command.NEW_SESSION, caps)["value"]
.venv/lib/python3.12/site-packages/bstack_utils/bstack1ll1l1ll1l_opy_.py:29: in execute
response = self._1lllll11111_opy_(this, driver_command, *args, **kwargs)
.venv/lib/python3.12/site-packages/browserstack_sdk/__init__.py:1117: in bstack1lllllll11_opy_
response = bstack1llll1111_opy_(self, driver_command, *args, **kwargs)
.venv/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py:347: in execute
self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x7fe073d3b290>
response = {'sessionId': '', 'status': 13, 'value': {'error': 'The property \'#/alwaysMatch/bstack:options\' contains additional ...ontains additional properties ["disableAutoCaptureLogs"] outside of the schema when none are allowed in the payload.'}}
def check_response(self, response: Dict[str, Any]) -> None:
"""Checks that a JSON response from the WebDriver does not have an
error.
:Args:
- response - The JSON response from the WebDriver server as a dictionary
object.
:Raises: If the response contains an error message.
"""
status = response.get("status", None)
if not status or status == ErrorCode.SUCCESS:
return
value = None
message = response.get("message", "")
screen: str = response.get("screen", "")
stacktrace = None
if isinstance(status, int):
value_json = response.get("value", None)
if value_json and isinstance(value_json, str):
import json
try:
value = json.loads(value_json)
if len(value) == 1:
value = value["value"]
status = value.get("error", None)
if not status:
status = value.get("status", ErrorCode.UNKNOWN_ERROR)
message = value.get("value") or value.get("message")
if not isinstance(message, str):
value = message
message = message.get("message")
else:
message = value.get("message", None)
except ValueError:
pass
exception_class: Type[WebDriverException]
e = ErrorCode()
error_codes = [item for item in dir(e) if not item.startswith("__")]
for error_code in error_codes:
error_info = getattr(ErrorCode, error_code)
if isinstance(error_info, list) and status in error_info:
exception_class = getattr(ExceptionMapping, error_code, WebDriverException)
break
else:
exception_class = WebDriverException
if not value:
value = response["value"]
if isinstance(value, str):
raise exception_class(value)
if message == "" and "message" in value:
message = value["message"]
screen = None # type: ignore[assignment]
if "screen" in value:
screen = value["screen"]
stacktrace = None
st_value = value.get("stackTrace") or value.get("stacktrace")
if st_value:
if isinstance(st_value, str):
stacktrace = st_value.split("\n")
else:
stacktrace = []
try:
for frame in st_value:
line = frame.get("lineNumber", "")
file = frame.get("fileName", "<anonymous>")
if line:
file = f"{file}:{line}"
meth = frame.get("methodName", "<anonymous>")
if "className" in frame:
meth = f"{frame['className']}.{meth}"
msg = " at %s (%s)"
msg = msg % (meth, file)
stacktrace.append(msg)
except TypeError:
pass
if exception_class == UnexpectedAlertPresentException:
alert_text = None
if "data" in value:
alert_text = value["data"].get("text")
elif "alert" in value:
alert_text = value["alert"].get("text")
raise exception_class(message, screen, stacktrace, alert_text) # type: ignore[call-arg] # mypy is not smart enough here
> raise exception_class(message, screen, stacktrace)
E selenium.common.exceptions.WebDriverException: Message: The property '#/alwaysMatch/bstack:options' contains additional properties ["disableAutoCaptureLogs"] outside of the schema when none are allowed in the payload.
.venv/lib/python3.12/site-packages/selenium/webdriver/remote/errorhandler.py:229: WebDriverException ```
@NurlanMirovich The issue you are facing currently is fixed in 1.19.19 version of browserstack-sdk
. Can you please upgrade your browserstack-sdk
package to the latest 1.19.24 and try out once?
Let me know if you available for a quick call to resolve this issue faster
Hi @sriteja777 i should be able to jump on a call with you... i updated but still minor issues
All of the tests are failing for some reason, and how do i disable the BS logs, i just want those in green
Stacktrace:
0 chromedriver 0x000000010c9d70f8 chromedriver + 4595960
1 chromedriver 0x000000010c9cee63 chromedriver + 4562531
2 chromedriver 0x000000010c5d239a chromedriver + 381850
3 chromedriver 0x000000010c61bf08 chromedriver + 683784
4 chromedriver 0x000000010c61c191 chromedriver + 684433
5 chromedriver 0x000000010c660b14 chromedriver + 965396
6 chromedriver 0x000000010c63e16d chromedriver + 823661
7 chromedriver 0x000000010c65e14d chromedriver + 954701
8 chromedriver 0x000000010c63dee3 chromedriver + 823011
9 chromedriver 0x000000010c60ebe4 chromedriver + 629732
10 chromedriver 0x000000010c60f79e chromedriver + 632734
11 chromedriver 0x000000010c99d012 chromedriver + 4358162
12 chromedriver 0x000000010c9a1c5d chromedriver + 4377693
13 chromedriver 0x000000010c9a15d3 chromedriver + 4376019
14 chromedriver 0x000000010c9a1f05 chromedriver + 4378373
15 chromedriver 0x000000010c986a35 chromedriver + 4266549
16 chromedriver 0x000000010c9a228d chromedriver + 4379277
17 chromedriver 0x000000010c979080 chromedriver + 4210816
18 chromedriver 0x000000010c9bfac8 chromedriver + 4500168
19 chromedriver 0x000000010c9bfc41 chromedriver + 4500545
20 chromedriver 0x000000010c9ceaa3 chromedriver + 4561571
21 libsystem_pthread.dylib 0x00007fff204fd8fc _pthread_start + 224
22 libsystem_pthread.dylib 0x00007fff204f9443 thread_start + 15
FAILED tests/step_defs/test_core_app.py::test_recent_transactions_up_to_the_last_5_are_presented_on_the_overview_screen - selenium.common.exceptions.TimeoutException: Message:
FAILED tests/step_defs/test_core_app.py::test_account_info__when_selected_loads_the_account_info_screen_1 - selenium.common.exceptions.TimeoutException: Message:
Stacktrace:
0 chromedriver 0x00000001069830f8 chromedriver + 4595960
1 chromedriver 0x000000010697ae63 chromedriver + 4562531
2 chromedriver 0x000000010657e39a chromedriver + 381850
3 chromedriver 0x00000001065c7f08 chromedriver + 683784
4 chromedriver 0x00000001065c8191 chromedriver + 684433
5 chromedriver 0x000000010660cb14 chromedriver + 965396
6 chromedriver 0x00000001065ea16d chromedriver + 823661 ```
Ganesh, i have updated the requirements.txt to 23 and tried to run again... also i removed parallelRun from the BS yaml file
When configuring logging in pytest the github actions are throwing BS logs
BS is not able to handle the logging level -> also have pytest.ini config file