Best Python code snippet using autotest_python
views.py
Source:views.py  
1from urllib.parse import urlparse, urlunparse2from django.conf import settings3# Avoid shadowing the login() and logout() views below.4from django.contrib.auth import (5    REDIRECT_FIELD_NAME, get_user_model, login as auth_login,6    logout as auth_logout, update_session_auth_hash,7)8from django.contrib.auth.decorators import login_required9from django.contrib.auth.forms import (10    AuthenticationForm, PasswordChangeForm, PasswordResetForm, SetPasswordForm,11)12from django.contrib.auth.tokens import default_token_generator13from django.contrib.sites.shortcuts import get_current_site14from django.core.exceptions import ValidationError15from django.http import HttpResponseRedirect, QueryDict16from django.shortcuts import resolve_url17from django.urls import reverse_lazy18from django.utils.decorators import method_decorator19from django.utils.http import (20    url_has_allowed_host_and_scheme, urlsafe_base64_decode,21)22from django.utils.translation import gettext_lazy as _23from django.views.decorators.cache import never_cache24from django.views.decorators.csrf import csrf_protect25from django.views.decorators.debug import sensitive_post_parameters26from django.views.generic.base import TemplateView27from django.views.generic.edit import FormView28UserModel = get_user_model()29class SuccessURLAllowedHostsMixin:30    success_url_allowed_hosts = set()31    def get_success_url_allowed_hosts(self):32        return {self.request.get_host(), *self.success_url_allowed_hosts}33class LoginView(SuccessURLAllowedHostsMixin, FormView):34    """35    Display the login form and handle the login action.36    """37    form_class = AuthenticationForm38    authentication_form = None39    redirect_field_name = REDIRECT_FIELD_NAME40    template_name = 'registration/login.html'41    redirect_authenticated_user = False42    extra_context = None43    @method_decorator(sensitive_post_parameters())44    @method_decorator(csrf_protect)45    @method_decorator(never_cache)46    def dispatch(self, request, *args, **kwargs):47        if self.redirect_authenticated_user and self.request.user.is_authenticated:48            redirect_to = self.get_success_url()49            if redirect_to == self.request.path:50                raise ValueError(51                    "Redirection loop for authenticated user detected. Check that "52                    "your LOGIN_REDIRECT_URL doesn't point to a login page."53                )54            return HttpResponseRedirect(redirect_to)55        return super().dispatch(request, *args, **kwargs)56    def get_success_url(self):57        url = self.get_redirect_url()58        return url or resolve_url(settings.LOGIN_REDIRECT_URL)59    def get_redirect_url(self):60        """Return the user-originating redirect URL if it's safe."""61        redirect_to = self.request.POST.get(62            self.redirect_field_name,63            self.request.GET.get(self.redirect_field_name, '')64        )65        url_is_safe = url_has_allowed_host_and_scheme(66            url=redirect_to,67            allowed_hosts=self.get_success_url_allowed_hosts(),68            require_https=self.request.is_secure(),69        )70        return redirect_to if url_is_safe else ''71    def get_form_class(self):72        return self.authentication_form or self.form_class73    def get_form_kwargs(self):74        kwargs = super().get_form_kwargs()75        kwargs['request'] = self.request76        return kwargs77    def form_valid(self, form):78        """Security check complete. Log the user in."""79        auth_login(self.request, form.get_user())80        return HttpResponseRedirect(self.get_success_url())81    def get_context_data(self, **kwargs):82        context = super().get_context_data(**kwargs)83        current_site = get_current_site(self.request)84        context.update({85            self.redirect_field_name: self.get_redirect_url(),86            'site': current_site,87            'site_name': current_site.name,88            **(self.extra_context or {})89        })90        return context91class LogoutView(SuccessURLAllowedHostsMixin, TemplateView):92    """93    Log out the user and display the 'You are logged out' message.94    """95    next_page = None96    redirect_field_name = REDIRECT_FIELD_NAME97    template_name = 'registration/logged_out.html'98    extra_context = None99    @method_decorator(never_cache)100    def dispatch(self, request, *args, **kwargs):101        auth_logout(request)102        next_page = self.get_next_page()103        if next_page:104            # Redirect to this page until the session has been cleared.105            return HttpResponseRedirect(next_page)106        return super().dispatch(request, *args, **kwargs)107    def post(self, request, *args, **kwargs):108        """Logout may be done via POST."""109        return self.get(request, *args, **kwargs)110    def get_next_page(self):111        if self.next_page is not None:112            next_page = resolve_url(self.next_page)113        elif settings.LOGOUT_REDIRECT_URL:114            next_page = resolve_url(settings.LOGOUT_REDIRECT_URL)115        else:116            next_page = self.next_page117        if (self.redirect_field_name in self.request.POST or118                self.redirect_field_name in self.request.GET):119            next_page = self.request.POST.get(120                self.redirect_field_name,121                self.request.GET.get(self.redirect_field_name)122            )123            url_is_safe = url_has_allowed_host_and_scheme(124                url=next_page,125                allowed_hosts=self.get_success_url_allowed_hosts(),126                require_https=self.request.is_secure(),127            )128            # Security check -- Ensure the user-originating redirection URL is129            # safe.130            if not url_is_safe:131                next_page = self.request.path132        return next_page133    def get_context_data(self, **kwargs):134        context = super().get_context_data(**kwargs)135        current_site = get_current_site(self.request)136        context.update({137            'site': current_site,138            'site_name': current_site.name,139            'title': _('Logged out'),140            **(self.extra_context or {})141        })142        return context143def logout_then_login(request, login_url=None):144    """145    Log out the user if they are logged in. Then redirect to the login page.146    """147    login_url = resolve_url(login_url or settings.LOGIN_URL)148    return LogoutView.as_view(next_page=login_url)(request)149def redirect_to_login(next, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):150    """151    Redirect the user to the login page, passing the given 'next' page.152    """153    resolved_url = resolve_url(login_url or settings.LOGIN_URL)154    login_url_parts = list(urlparse(resolved_url))155    if redirect_field_name:156        querystring = QueryDict(login_url_parts[4], mutable=True)157        querystring[redirect_field_name] = next158        login_url_parts[4] = querystring.urlencode(safe='/')159    return HttpResponseRedirect(urlunparse(login_url_parts))160# Class-based password reset views161# - PasswordResetView sends the mail162# - PasswordResetDoneView shows a success message for the above163# - PasswordResetConfirmView checks the link the user clicked and164#   prompts for a new password165# - PasswordResetCompleteView shows a success message for the above166class PasswordContextMixin:167    extra_context = None168    def get_context_data(self, **kwargs):169        context = super().get_context_data(**kwargs)170        context.update({171            'title': self.title,172            **(self.extra_context or {})173        })174        return context175class PasswordResetView(PasswordContextMixin, FormView):176    email_template_name = 'registration/password_reset_email.html'177    extra_email_context = None178    form_class = PasswordResetForm179    from_email = None180    html_email_template_name = None181    subject_template_name = 'registration/password_reset_subject.txt'182    success_url = reverse_lazy('password_reset_done')183    template_name = 'registration/password_reset_form.html'184    title = _('Password reset')185    token_generator = default_token_generator186    @method_decorator(csrf_protect)187    def dispatch(self, *args, **kwargs):188        return super().dispatch(*args, **kwargs)189    def form_valid(self, form):190        opts = {191            'use_https': self.request.is_secure(),192            'token_generator': self.token_generator,193            'from_email': self.from_email,194            'email_template_name': self.email_template_name,195            'subject_template_name': self.subject_template_name,196            'request': self.request,197            'html_email_template_name': self.html_email_template_name,198            'extra_email_context': self.extra_email_context,199        }200        form.save(**opts)201        return super().form_valid(form)202INTERNAL_RESET_SESSION_TOKEN = '_password_reset_token'203class PasswordResetDoneView(PasswordContextMixin, TemplateView):204    template_name = 'registration/password_reset_done.html'205    title = _('Password reset sent')206class PasswordResetConfirmView(PasswordContextMixin, FormView):207    form_class = SetPasswordForm208    post_reset_login = False209    post_reset_login_backend = None210    reset_url_token = 'set-password'211    success_url = reverse_lazy('password_reset_complete')212    template_name = 'registration/password_reset_confirm.html'213    title = _('Enter new password')214    token_generator = default_token_generator215    @method_decorator(sensitive_post_parameters())216    @method_decorator(never_cache)217    def dispatch(self, *args, **kwargs):218        assert 'uidb64' in kwargs and 'token' in kwargs219        self.validlink = False220        self.user = self.get_user(kwargs['uidb64'])221        if self.user is not None:222            token = kwargs['token']223            if token == self.reset_url_token:224                session_token = self.request.session.get(INTERNAL_RESET_SESSION_TOKEN)225                if self.token_generator.check_token(self.user, session_token):226                    # If the token is valid, display the password reset form.227                    self.validlink = True228                    return super().dispatch(*args, **kwargs)229            else:230                if self.token_generator.check_token(self.user, token):231                    # Store the token in the session and redirect to the232                    # password reset form at a URL without the token. That233                    # avoids the possibility of leaking the token in the234                    # HTTP Referer header.235                    self.request.session[INTERNAL_RESET_SESSION_TOKEN] = token236                    redirect_url = self.request.path.replace(token, self.reset_url_token)237                    return HttpResponseRedirect(redirect_url)238        # Display the "Password reset unsuccessful" page.239        return self.render_to_response(self.get_context_data())240    def get_user(self, uidb64):241        try:242            # urlsafe_base64_decode() decodes to bytestring243            uid = urlsafe_base64_decode(uidb64).decode()244            user = UserModel._default_manager.get(pk=uid)245        except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist, ValidationError):246            user = None247        return user248    def get_form_kwargs(self):249        kwargs = super().get_form_kwargs()250        kwargs['user'] = self.user251        return kwargs252    def form_valid(self, form):253        user = form.save()254        del self.request.session[INTERNAL_RESET_SESSION_TOKEN]255        if self.post_reset_login:256            auth_login(self.request, user, self.post_reset_login_backend)257        return super().form_valid(form)258    def get_context_data(self, **kwargs):259        context = super().get_context_data(**kwargs)260        if self.validlink:261            context['validlink'] = True262        else:263            context.update({264                'form': None,265                'title': _('Password reset unsuccessful'),266                'validlink': False,267            })268        return context269class PasswordResetCompleteView(PasswordContextMixin, TemplateView):270    template_name = 'registration/password_reset_complete.html'271    title = _('Password reset complete')272    def get_context_data(self, **kwargs):273        context = super().get_context_data(**kwargs)274        context['login_url'] = resolve_url(settings.LOGIN_URL)275        return context276class PasswordChangeView(PasswordContextMixin, FormView):277    form_class = PasswordChangeForm278    success_url = reverse_lazy('password_change_done')279    template_name = 'registration/password_change_form.html'280    title = _('Password change')281    @method_decorator(sensitive_post_parameters())282    @method_decorator(csrf_protect)283    @method_decorator(login_required)284    def dispatch(self, *args, **kwargs):285        return super().dispatch(*args, **kwargs)286    def get_form_kwargs(self):287        kwargs = super().get_form_kwargs()288        kwargs['user'] = self.request.user289        return kwargs290    def form_valid(self, form):291        form.save()292        # Updating the password logs out all other sessions for the user293        # except the current one.294        update_session_auth_hash(self.request, form.user)295        return super().form_valid(form)296class PasswordChangeDoneView(PasswordContextMixin, TemplateView):297    template_name = 'registration/password_change_done.html'298    title = _('Password change successful')299    @method_decorator(login_required)300    def dispatch(self, *args, **kwargs):...retry.py
Source:retry.py  
1import time2import logging3from ..exceptions import (4    ConnectTimeoutError,5    MaxRetryError,6    ProtocolError,7    ReadTimeoutError,8    ResponseError,9)10from ..packages import six11log = logging.getLogger(__name__)12class Retry(object):13    """ Retry configuration.14    Each retry attempt will create a new Retry object with updated values, so15    they can be safely reused.16    Retries can be defined as a default for a pool::17        retries = Retry(connect=5, read=2, redirect=5)18        http = PoolManager(retries=retries)19        response = http.request('GET', 'http://example.com/')20    Or per-request (which overrides the default for the pool)::21        response = http.request('GET', 'http://example.com/', retries=Retry(10))22    Retries can be disabled by passing ``False``::23        response = http.request('GET', 'http://example.com/', retries=False)24    Errors will be wrapped in :class:`~urllib3.exceptions.MaxRetryError` unless25    retries are disabled, in which case the causing exception will be raised.26    :param int total:27        Total number of retries to allow. Takes precedence over other counts.28        Set to ``None`` to remove this constraint and fall back on other29        counts. It's a good idea to set this to some sensibly-high value to30        account for unexpected edge cases and avoid infinite retry loops.31        Set to ``0`` to fail on the first retry.32        Set to ``False`` to disable and imply ``raise_on_redirect=False``.33    :param int connect:34        How many connection-related errors to retry on.35        These are errors raised before the request is sent to the remote server,36        which we assume has not triggered the server to process the request.37        Set to ``0`` to fail on the first retry of this type.38    :param int read:39        How many times to retry on read errors.40        These errors are raised after the request was sent to the server, so the41        request may have side-effects.42        Set to ``0`` to fail on the first retry of this type.43    :param int redirect:44        How many redirects to perform. Limit this to avoid infinite redirect45        loops.46        A redirect is a HTTP response with a status code 301, 302, 303, 307 or47        308.48        Set to ``0`` to fail on the first retry of this type.49        Set to ``False`` to disable and imply ``raise_on_redirect=False``.50    :param iterable method_whitelist:51        Set of uppercased HTTP method verbs that we should retry on.52        By default, we only retry on methods which are considered to be53        indempotent (multiple requests with the same parameters end with the54        same state). See :attr:`Retry.DEFAULT_METHOD_WHITELIST`.55    :param iterable status_forcelist:56        A set of HTTP status codes that we should force a retry on.57        By default, this is disabled with ``None``.58    :param float backoff_factor:59        A backoff factor to apply between attempts. urllib3 will sleep for::60            {backoff factor} * (2 ^ ({number of total retries} - 1))61        seconds. If the backoff_factor is 0.1, then :func:`.sleep` will sleep62        for [0.1s, 0.2s, 0.4s, ...] between retries. It will never be longer63        than :attr:`Retry.MAX_BACKOFF`.64        By default, backoff is disabled (set to 0).65    :param bool raise_on_redirect: Whether, if the number of redirects is66        exhausted, to raise a MaxRetryError, or to return a response with a67        response code in the 3xx range.68    """69    DEFAULT_METHOD_WHITELIST = frozenset([70        'HEAD', 'GET', 'PUT', 'DELETE', 'OPTIONS', 'TRACE'])71    #: Maximum backoff time.72    BACKOFF_MAX = 12073    def __init__(self, total=10, connect=None, read=None, redirect=None,74                 method_whitelist=DEFAULT_METHOD_WHITELIST, status_forcelist=None,75                 backoff_factor=0, raise_on_redirect=True, _observed_errors=0):76        self.total = total77        self.connect = connect78        self.read = read79        if redirect is False or total is False:80            redirect = 081            raise_on_redirect = False82        self.redirect = redirect83        self.status_forcelist = status_forcelist or set()84        self.method_whitelist = method_whitelist85        self.backoff_factor = backoff_factor86        self.raise_on_redirect = raise_on_redirect87        self._observed_errors = _observed_errors # TODO: use .history instead?88    def new(self, **kw):89        params = dict(90            total=self.total,91            connect=self.connect, read=self.read, redirect=self.redirect,92            method_whitelist=self.method_whitelist,93            status_forcelist=self.status_forcelist,94            backoff_factor=self.backoff_factor,95            raise_on_redirect=self.raise_on_redirect,96            _observed_errors=self._observed_errors,97        )98        params.update(kw)99        return type(self)(**params)100    @classmethod101    def from_int(cls, retries, redirect=True, default=None):102        """ Backwards-compatibility for the old retries format."""103        if retries is None:104            retries = default if default is not None else cls.DEFAULT105        if isinstance(retries, Retry):106            return retries107        redirect = bool(redirect) and None108        new_retries = cls(retries, redirect=redirect)109        log.debug("Converted retries value: %r -> %r" % (retries, new_retries))110        return new_retries111    def get_backoff_time(self):112        """ Formula for computing the current backoff113        :rtype: float114        """115        if self._observed_errors <= 1:116            return 0117        backoff_value = self.backoff_factor * (2 ** (self._observed_errors - 1))118        return min(self.BACKOFF_MAX, backoff_value)119    def sleep(self):120        """ Sleep between retry attempts using an exponential backoff.121        By default, the backoff factor is 0 and this method will return122        immediately.123        """124        backoff = self.get_backoff_time()125        if backoff <= 0:126            return127        time.sleep(backoff)128    def _is_connection_error(self, err):129        """ Errors when we're fairly sure that the server did not receive the130        request, so it should be safe to retry.131        """132        return isinstance(err, ConnectTimeoutError)133    def _is_read_error(self, err):134        """ Errors that occur after the request has been started, so we should135        assume that the server began processing it.136        """137        return isinstance(err, (ReadTimeoutError, ProtocolError))138    def is_forced_retry(self, method, status_code):139        """ Is this method/status code retryable? (Based on method/codes whitelists)140        """141        if self.method_whitelist and method.upper() not in self.method_whitelist:142            return False143        return self.status_forcelist and status_code in self.status_forcelist144    def is_exhausted(self):145        """ Are we out of retries? """146        retry_counts = (self.total, self.connect, self.read, self.redirect)147        retry_counts = list(filter(None, retry_counts))148        if not retry_counts:149            return False150        return min(retry_counts) < 0151    def increment(self, method=None, url=None, response=None, error=None, _pool=None, _stacktrace=None):152        """ Return a new Retry object with incremented retry counters.153        :param response: A response object, or None, if the server did not154            return a response.155        :type response: :class:`~urllib3.response.HTTPResponse`156        :param Exception error: An error encountered during the request, or157            None if the response was received successfully.158        :return: A new ``Retry`` object.159        """160        if self.total is False and error:161            # Disabled, indicate to re-raise the error.162            raise six.reraise(type(error), error, _stacktrace)163        total = self.total164        if total is not None:165            total -= 1166        _observed_errors = self._observed_errors167        connect = self.connect168        read = self.read169        redirect = self.redirect170        cause = 'unknown'171        if error and self._is_connection_error(error):172            # Connect retry?173            if connect is False:174                raise six.reraise(type(error), error, _stacktrace)175            elif connect is not None:176                connect -= 1177            _observed_errors += 1178        elif error and self._is_read_error(error):179            # Read retry?180            if read is False:181                raise six.reraise(type(error), error, _stacktrace)182            elif read is not None:183                read -= 1184            _observed_errors += 1185        elif response and response.get_redirect_location():186            # Redirect retry?187            if redirect is not None:188                redirect -= 1189            cause = 'too many redirects'190        else:191            # Incrementing because of a server error like a 500 in192            # status_forcelist and a the given method is in the whitelist193            _observed_errors += 1194            cause = ResponseError.GENERIC_ERROR195            if response and response.status:196                cause = ResponseError.SPECIFIC_ERROR.format(197                    status_code=response.status)198        new_retry = self.new(199            total=total,200            connect=connect, read=read, redirect=redirect,201            _observed_errors=_observed_errors)202        if new_retry.is_exhausted():203            raise MaxRetryError(_pool, url, error or ResponseError(cause))204        log.debug("Incremented Retry for (url='%s'): %r" % (url, new_retry))205        return new_retry206    def __repr__(self):207        return ('{cls.__name__}(total={self.total}, connect={self.connect}, '208                'read={self.read}, redirect={self.redirect})').format(209                    cls=type(self), self=self)210# For backwards compatibility (equivalent to pre-v1.9):...redirector2.py
Source:redirector2.py  
...34                return35            else:36                self.server.printer.warn("No 'Content-Length' received")37        self._log()38    def _send_redirect(self):39        redirect_url = self.server.ssrf_url40        if self.server.expand:41            if redirect_url.endswith('/'):42                redirect_url = redirect_url[:-1]43            redirect_url += self.path44        self.server.printer.debug("Redirecting with {} to {}".format(self.server.redirect_code, redirect_url))45        self.send_response(self.server.redirect_code)46        self.send_header('Location', redirect_url)47        self.end_headers()48    def do_GET(self):49        self._log()50        self._send_redirect()51    def do_HEAD(self):52        self._log()53        self._send_redirect()54    def do_POST(self):55        self._log_with_body()56        self._send_redirect()57    def do_PUT(self):58        self._log_with_body()59        self._send_redirect()60    def do_DELETE(self):61        self._log()62        self._send_redirect()63    def do_PATCH(self):64        self._log_with_body()65        self._send_redirect()66    def do_OPTIONS(self):67        self._log()68        self._send_redirect()69    def log_message(self, format, *args):70        # suppress default access logs71        return72class RedirectHTTPServer(HTTPServer):73    def __init__(self, printer, args, server_address, RequestHandlerClass=Redirect, bind_and_activate=True):74        super().__init__(server_address, RequestHandlerClass, bind_and_activate)75        self.printer = printer76        self.ssrf_url = args.ssrf_url77        self.redirect_code = args.redirect_code78        self.quiet = args.quiet79        self.expand = args.expand80class Printer:81    DEBUG = '\033[90m'82    PURPLE = '\033[95m'...test_iostream.py
Source:test_iostream.py  
...65    assert capture == "ab"66def test_flush(capfd):67    msg = "(not flushed)"68    msg2 = "(flushed)"69    with m.ostream_redirect():70        m.noisy_function(msg, flush=False)71        stdout, stderr = capfd.readouterr()72        assert stdout == ''73        m.noisy_function(msg2, flush=True)74        stdout, stderr = capfd.readouterr()75        assert stdout == msg + msg276        m.noisy_function(msg, flush=False)77    stdout, stderr = capfd.readouterr()78    assert stdout == msg79def test_not_captured(capfd):80    msg = "Something that should not show up in log"81    stream = StringIO()82    with redirect_stdout(stream):83        m.raw_output(msg)84    stdout, stderr = capfd.readouterr()85    assert stdout == msg86    assert stderr == ''87    assert stream.getvalue() == ''88    stream = StringIO()89    with redirect_stdout(stream):90        m.captured_output(msg)91    stdout, stderr = capfd.readouterr()92    assert stdout == ''93    assert stderr == ''94    assert stream.getvalue() == msg95def test_err(capfd):96    msg = "Something that should not show up in log"97    stream = StringIO()98    with redirect_stderr(stream):99        m.raw_err(msg)100    stdout, stderr = capfd.readouterr()101    assert stdout == ''102    assert stderr == msg103    assert stream.getvalue() == ''104    stream = StringIO()105    with redirect_stderr(stream):106        m.captured_err(msg)107    stdout, stderr = capfd.readouterr()108    assert stdout == ''109    assert stderr == ''110    assert stream.getvalue() == msg111def test_multi_captured(capfd):112    stream = StringIO()113    with redirect_stdout(stream):114        m.captured_output("a")115        m.raw_output("b")116        m.captured_output("c")117        m.raw_output("d")118    stdout, stderr = capfd.readouterr()119    assert stdout == 'bd'120    assert stream.getvalue() == 'ac'121def test_dual(capsys):122    m.captured_dual("a", "b")123    stdout, stderr = capsys.readouterr()124    assert stdout == "a"125    assert stderr == "b"126def test_redirect(capfd):127    msg = "Should not be in log!"128    stream = StringIO()129    with redirect_stdout(stream):130        m.raw_output(msg)131    stdout, stderr = capfd.readouterr()132    assert stdout == msg133    assert stream.getvalue() == ''134    stream = StringIO()135    with redirect_stdout(stream):136        with m.ostream_redirect():137            m.raw_output(msg)138    stdout, stderr = capfd.readouterr()139    assert stdout == ''140    assert stream.getvalue() == msg141    stream = StringIO()142    with redirect_stdout(stream):143        m.raw_output(msg)144    stdout, stderr = capfd.readouterr()145    assert stdout == msg146    assert stream.getvalue() == ''147def test_redirect_err(capfd):148    msg = "StdOut"149    msg2 = "StdErr"150    stream = StringIO()151    with redirect_stderr(stream):152        with m.ostream_redirect(stdout=False):153            m.raw_output(msg)154            m.raw_err(msg2)155    stdout, stderr = capfd.readouterr()156    assert stdout == msg157    assert stderr == ''158    assert stream.getvalue() == msg2159def test_redirect_both(capfd):160    msg = "StdOut"161    msg2 = "StdErr"162    stream = StringIO()163    stream2 = StringIO()164    with redirect_stdout(stream):165        with redirect_stderr(stream2):166            with m.ostream_redirect():167                m.raw_output(msg)168                m.raw_err(msg2)169    stdout, stderr = capfd.readouterr()170    assert stdout == ''171    assert stderr == ''172    assert stream.getvalue() == msg...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
