Solucionado (ver solução)
Solucionado
(ver solução)
9
respostas

[Bug] Selenium não encontra o webdriver no Jenkins

Olá, estou com um problema no curso "Scripting: automação de tarefas com Python e criação de Pipelines no Jenkins", onde ao rodar o Selenium localmente, tudo funciona, mas ao rodar via Jenkins, mesmo com a aplicação rodando, fico recebendo erro de que não foi encontrado o webdriver, poderiam me auxiliar?

** Já pesquisei em inúmeros fóruns na internet, e não obtive êxito
** Ao rodar fora do python3 -m, ele nem sequer consegue encontrar o selenium, mesmo tendo instalado via apt install -y python3-pytest python3-selenium

9 respostas

Erro:

python3 -m pytest
============================= test session starts ==============================
[...]

==================================== ERRORS ====================================
_________________________ ERROR at setup of test_home __________________________

service = <selenium.webdriver.chrome.service.Service object at 0x7f277bad65a0>
options = <selenium.webdriver.chrome.options.Options object at 0x7f277bd45af0>

    @staticmethod
    def get_path(service: Service, options: BaseOptions) -> str:
        path = service.path
        try:
>           path = SeleniumManager().driver_location(options) if path is None else path

/usr/lib/python3/dist-packages/selenium/webdriver/common/driver_finder.py:38: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/lib/python3/dist-packages/selenium/webdriver/common/selenium_manager.py:89: in driver_location
    args = [str(self.get_binary()), "--browser", browser]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    [...]

/usr/lib/python3/dist-packages/selenium/webdriver/common/selenium_manager.py:73: WebDriverException

The above exception was the direct cause of the following exception:

    @pytest.fixture(scope="module")
    
    def browser():
        # Configuração do webdriver
        chrome_options = webdriver.ChromeOptions()
        chrome_options.add_argument("--headless")
        chrome_options.add_argument("--disable-gpu")
>       driver = webdriver.Chrome(options=chrome_options)

conftest.py:12: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/lib/python3/dist-packages/selenium/webdriver/chrome/webdriver.py:45: in __init__
    super().__init__(
/usr/lib/python3/dist-packages/selenium/webdriver/chromium/webdriver.py:49: in __init__
    self.service.path = DriverFinder.get_path(self.service, options)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

service = <selenium.webdriver.chrome.service.Service object at 0x7f277bad65a0>
options = <selenium.webdriver.chrome.options.Options object at 0x7f277bd45af0>

    @staticmethod
    def get_path(service: Service, options: BaseOptions) -> str:
        path = service.path
        try:
            path = SeleniumManager().driver_location(options) if path is None else path
        except Exception as err:
            msg = f"Unable to obtain driver for {options.capabilities['browserName']} using Selenium Manager."
>           raise NoSuchDriverException(msg) from err
E           selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for chrome using Selenium Manager.; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location

/usr/lib/python3/dist-packages/selenium/webdriver/common/driver_finder.py:41: NoSuchDriverException
=========================== short test summary info ============================
ERROR tests/test_home.py::test_home - selenium.common.exceptions.NoSuchDriverException: Message: Unable to obtain driver for chrome using Selenium Manager.; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/driver_location
=============================== 1 error in 0.04s ===============================
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
ERROR: script returned exit code 1
Finished: FAILURE

** Tive de remover parte do erro por conta do limite de caracteres aqui no post.

Oi, Murilo! Como vai?

O erro indica que o Selenium não consegue encontrar o WebDriver do Chrome quando executado dentro do Jenkins. Isso acontece porque o Selenium Manager não localiza o binário do driver automaticamente no ambiente isolado do Jenkins (como containers, agentes remotos ou ambientes headless).

Para resolver isso, defina manualmente o caminho do ChromeDriver e certifique-se de que o Chrome também esteja instalado no ambiente Jenkins. Faça assim:

  1. Instale o Chrome e o ChromeDriver no ambiente Jenkins.

  2. Descubra o caminho do chromedriver com which chromedriver ou instale via apt:

    sudo apt update
    sudo apt install -y chromium-chromedriver
    
  3. No seu fixture de teste, informe explicitamente o caminho do driver:

    import pytest
    from selenium import webdriver
    from selenium.webdriver.chrome.service import Service
    from selenium.webdriver.chrome.options import Options
    
    @pytest.fixture(scope="module")
    def browser():
        chrome_options = Options()
        chrome_options.add_argument("--headless")
        chrome_options.add_argument("--disable-gpu")
        # Caminho fixo do driver
        service = Service(executable_path="/usr/lib/chromium-browser/chromedriver")
        driver = webdriver.Chrome(service=service, options=chrome_options)
        yield driver
        driver.quit()
    

Se estiver usando um container, certifique-se que o caminho está correto dentro da imagem. Pode ser necessário copiar o chromedriver manualmente ou usar uma imagem base com ele incluso.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.

@Armando fiz essas etapas conforme informou, mas o erro persiste, ao rodar localmente fora do Jenkins, funciona normalmente, é apenas no Jenkins que o erro acontece. Um ponto importante, é, após aplicar o código que passou, o erro tem variado entre o que postei, e este outro:

_________________________ ERROR at setup of test_home __________________________
    @pytest.fixture(scope="module")
    
    def browser():
        # Configuração do webdriver
        chrome_options = Options()
        chrome_options.add_argument("--headless")
        chrome_options.add_argument("--disable-gpu")
        chrome_options.add_argument("--no-sandbox")
        service=Service(executable_path="/usr/bin/chromedriver")
>       driver=webdriver.Chrome(service=service, options=chrome_options)
conftest.py:17: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/lib/python3/dist-packages/selenium/webdriver/chrome/webdriver.py:45: in __init__
    super().__init__(
/usr/lib/python3/dist-packages/selenium/webdriver/chromium/webdriver.py:50: in __init__
    self.service.start()
/usr/lib/python3/dist-packages/selenium/webdriver/common/service.py:102: in start
    self.assert_process_still_running()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = <selenium.webdriver.chrome.service.Service object at 0x7f18d3d0ba70>
    def assert_process_still_running(self) -> None:
        """Check if the underlying process is still running."""
        return_code = self.process.poll()
        if return_code:
>           raise WebDriverException(f"Service {self._path} unexpectedly exited. Status code was: {return_code}")
E           selenium.common.exceptions.WebDriverException: Message: Service /usr/bin/chromedriver unexpectedly exited. Status code was: 1
/usr/lib/python3/dist-packages/selenium/webdriver/common/service.py:115: WebDriverException
=========================== short test summary info ============================
ERROR tests/test_home.py::test_home - selenium.common.exceptions.WebDriverException: Message: Service /usr/bin/chromedriver unexpectedly exited. Status code was: 1
=============================== 1 error in 0.10s ===============================
script returned exit code 1

** Após isso, também adicionei o --no-sandbox para ver se funcionaria sem emulações, mas são os mesmos erros.

Oi, Murilo!

Obrigado por trazer mais contexto. O erro WebDriverException: Message: Service /usr/bin/chromedriver unexpectedly exited. Status code was: 1 mostra que o Jenkins está conseguindo encontrar o ChromeDriver, mas ele falha ao iniciar. Isso geralmente acontece por ausência de dependências gráficas ou por um chromedriver incompatível com a versão do Chrome.

Resolva fazendo o seguinte:

  1. Garanta que o Chrome e o ChromeDriver são compatíveis. Veja a versão do Chrome:

    
     google-chrome --version
     

    Veja a versão do ChromeDriver:

    
     chromedriver --version
     

    Se forem incompatíveis, instale versões correspondentes manualmente ou use o chromedriver da própria versão do Chrome com:

    
     apt install chromium-browser chromium-chromedriver
     
  2. Adicione dependências do sistema ao Jenkins (especialmente se estiver rodando em container ou ambiente headless):

    
     apt update && apt install -y \
         libglib2.0-0 \
         libnss3 \
         libgconf-2-4 \
         libfontconfig1 \
         libxss1 \
         libappindicator1 \
         libasound2 \
         libx11-xcb1 \
         libxcomposite1 \
         libxcursor1 \
         libxdamage1 \
         libxi6 \
         libxtst6 \
         libpangocairo-1.0-0 \
         libpango-1.0-0 \
         fonts-liberation \
         libatk-bridge2.0-0 \
         libgtk-3-0
     
  3. Confirme que o Chrome está com permissão para rodar em modo headless no ambiente Jenkins. Continue usando as opções que já aplicou:

    
     chrome_options.add_argument("--headless")
     chrome_options.add_argument("--disable-gpu")
     chrome_options.add_argument("--no-sandbox")
     chrome_options.add_argument("--disable-dev-shm-usage")
     

    Essas flags evitam falhas de inicialização por conta de falta de acesso a memória compartilhada ou sandboxing.

  4. Se o Jenkins estiver em um container, você pode precisar adicionar isso ao Dockerfile ou pipeline:

    
     RUN apt install -y chromium-browser chromium-chromedriver
     ENV PATH="/usr/lib/chromium-browser:${PATH}"
     

    Ou usar uma imagem base como:

    
     selenium/standalone-chrome
     
  5. Por fim, valide se o chromedriver consegue rodar manualmente no ambiente Jenkins com:

    
     chromedriver --version
     

Se ele travar ou falhar, há algum problema de sistema.

Fico à disposição.

Salve manow, mudaram os erros, agora to tomando permission denied numa pasta que o Jenkins é owner e tem permissão total kk

_________________________ ERROR at setup of test_home __________________________
    @pytest.fixture(scope="module")
    
    def browser():
        # Configuração do webdriver
        chrome_options = Options()
        chrome_options.add_argument("--headless")
        chrome_options.add_argument("--disable-gpu")
        chrome_options.add_argument("--no-sandbox")
        service=Service(executable_path="/home/mmelo/chrome-linux64/chrome")
>       driver=webdriver.Chrome(service=service, options=chrome_options)
conftest.py:17: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/lib/python3/dist-packages/selenium/webdriver/chrome/webdriver.py:45: in __init__
    super().__init__(
/usr/lib/python3/dist-packages/selenium/webdriver/chromium/webdriver.py:49: in __init__
    self.service.path = DriverFinder.get_path(self.service, options)
/usr/lib/python3/dist-packages/selenium/webdriver/common/driver_finder.py:43: in get_path
    if path is None or not Path(path).is_file():
/usr/lib/python3.12/pathlib.py:894: in is_file
    return S_ISREG(self.stat().st_mode)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = PosixPath('/home/mmelo/chrome-linux64/chrome')
    def stat(self, *, follow_symlinks=True):
        """
        Return the result of the stat() system call on this path, like
        os.stat() does.
        """
>       return os.stat(self, follow_symlinks=follow_symlinks)
E       PermissionError: [Errno 13] Permission denied: '/home/mmelo/chrome-linux64/chrome'
/usr/lib/python3.12/pathlib.py:842: PermissionError
=========================== short test summary info ============================
ERROR tests/test_home.py::test_home - PermissionError: [Errno 13] Permission denied: '/home/mmelo/chrome-linux64/chrome'

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Tentei também com o que está disponível em /usr/bin, mas é o mesmo erro :/

Um outro ponto interessante é, ao rodar sem especificar o chromedriver, ele continua tentando puxar da minha /home, mesmo não havendo quaisquer configurações específicas do Jenkins.

Oi, Murilo!

Bem normal consertar um erro e aparecer outros kkkk isso significa um avanço!

O erro PermissionError: [Errno 13] Permission denied: '/home/mmelo/chrome-linux64/chrome' mostra que o Jenkins até está conseguindo localizar o Chrome, mas não tem permissão para executar o binário diretamente da pasta da sua home. Isso acontece com frequência em ambientes CI/CD, onde o agente do Jenkins roda com permissões mais restritas por padrão (mesmo sendo dono da pasta).

Resolva fazendo o seguinte:

  1. Evite apontar diretamente para o binário do Chrome (chrome) como se fosse o driver.
    O que o Selenium espera no Service(executable_path=...) é o caminho do ChromeDriver, e não do navegador em si. Esse é um ponto crítico.

  2. Verifique se o ChromeDriver está realmente acessível e executável:
    Use um caminho como /usr/bin/chromedriver, e certifique-se de que ele tem permissão de execução:

    
     sudo chmod +x /usr/bin/chromedriver
     
  3. Se estiver usando o Chrome baixado manualmente em /home/mmelo, instale corretamente o Chrome e o ChromeDriver no sistema, para evitar esse tipo de conflito com permissões e caminhos esperados.

  4. Evite que o Selenium use o Selenium Manager e assuma o caminho manualmente com o Service correto. Exemplo ajustado:

    
     from selenium import webdriver
     from selenium.webdriver.chrome.options import Options
     from selenium.webdriver.chrome.service import Service
     import pytest
    
     @pytest.fixture(scope="module")
     def browser():
         chrome_options = Options()
         chrome_options.add_argument("--headless")
         chrome_options.add_argument("--disable-gpu")
         chrome_options.add_argument("--no-sandbox")
         chrome_options.add_argument("--disable-dev-shm-usage")
    
         service = Service(executable_path="/usr/bin/chromedriver")  # NÃO aponte para o chrome!
         driver = webdriver.Chrome(service=service, options=chrome_options)
         yield driver
         driver.quit()
     
  5. Garanta que o Jenkins está rodando como usuário que tem acesso total a esse /usr/bin/chromedriver e que o binário corresponde à versão do Chrome no sistema.

  6. Teste o driver diretamente no ambiente do Jenkins para validar se ele executa normalmente:

    
     /usr/bin/chromedriver --version
     

Se falhar aqui, o problema é com o binário, não com seu script.

Fico à disposição.

Nice, agora ele parou de sofrer com o path do webdriver kk mas o webdriver está falhando

_________________________ ERROR at setup of test_home __________________________
    @pytest.fixture(scope="module")
    
    def browser():
        # Configuração do webdriver
        chrome_options = Options()
        chrome_options.add_argument("--headless")
        chrome_options.add_argument("--disable-gpu")
        chrome_options.add_argument("--no-sandbox")
        service=Service(executable_path="/usr/bin/chromedriver")
>       driver=webdriver.Chrome(service=service, options=chrome_options)
conftest.py:17: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/lib/python3/dist-packages/selenium/webdriver/chrome/webdriver.py:45: in __init__
    super().__init__(
/usr/lib/python3/dist-packages/selenium/webdriver/chromium/webdriver.py:50: in __init__
    self.service.start()
/usr/lib/python3/dist-packages/selenium/webdriver/common/service.py:102: in start
    self.assert_process_still_running()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = <selenium.webdriver.chrome.service.Service object at 0x7f1674f06540>
    def assert_process_still_running(self) -> None:
        """Check if the underlying process is still running."""
        return_code = self.process.poll()
        if return_code:
>           raise WebDriverException(f"Service {self._path} unexpectedly exited. Status code was: {return_code}")
E           selenium.common.exceptions.WebDriverException: Message: Service /usr/bin/chromedriver unexpectedly exited. Status code was: 1
/usr/lib/python3/dist-packages/selenium/webdriver/common/service.py:115: WebDriverException
=========================== short test summary info ============================
ERROR tests/test_home.py::test_home - selenium.common.exceptions.WebDriverException: Message: Service /usr/bin/chromedriver unexpectedly exited. Status code was: 1
solução!

Oi, Murilo! Perdão pela demora em responder!

Agora sobre o novo, novo erro, o WebDriverException com status code 1 agora indica que o Jenkins encontra o ChromeDriver, mas ele falha ao iniciar o processo do navegador. Isso normalmente acontece quando o ChromeDriver e o Google Chrome (ou Chromium) não estão na mesma versão compatível ou quando faltam bibliotecas gráficas no ambiente.

Para resolver:

  1. Garanta que as versões batem:

    
    google-chrome --version
    chromedriver --version
    

    Se não coincidirem, reinstale para garantir compatibilidade:

    
    sudo apt update
    sudo apt install -y chromium-browser chromium-chromedriver
    
  2. Instale as bibliotecas necessárias para rodar o Chrome no ambiente headless:

    
    sudo apt install -y \
      libglib2.0-0 \
      libnss3 \
      libgconf-2-4 \
      libfontconfig1 \
      libxss1 \
      libappindicator1 \
      libasound2 \
      libx11-xcb1 \
      libxcomposite1 \
      libxcursor1 \
      libxdamage1 \
      libxi6 \
      libxtst6 \
      libpangocairo-1.0-0 \
      libpango-1.0-0 \
      fonts-liberation \
      libatk-bridge2.0-0 \
      libgtk-3-0
    
  3. Ajuste as flags do Chrome para rodar sem sandbox e com menos uso de memória compartilhada:

    
    chrome_options.add_argument("--headless")
    chrome_options.add_argument("--disable-gpu")
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    
  4. Confirme se o ChromeDriver inicia manualmente no Jenkins:

    
    /usr/bin/chromedriver --version
    

    Se não iniciar, o problema é de instalação ou dependências.

Depois desses ajustes, seu fixture deve ficar assim:


from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
import pytest

@pytest.fixture(scope="module")
def browser():
    chrome_options = Options()
    chrome_options.add_argument("--headless")
    chrome_options.add_argument("--disable-gpu")
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")

    service = Service(executable_path="/usr/bin/chromedriver")
    driver = webdriver.Chrome(service=service, options=chrome_options)
    yield driver
    driver.quit()

Fico à disposição.

Salve Armando, tudo bom?

Cara, dois pontos, aparentemente é uma falha do WSL, recriei o ambiente e usei suas sugestões num host virtualizado pelo vbox, e também na máquina host windows, e em ambos os casos funcionou.

O problema está provavelmente em algo no WSL, pois somente nele o erro ocorre.

Apliquei as correções no WSL também, mas continuo recebendo o mesmo erro do chromedriver com status code 1