Implementação do processo de upload de um arquivo de um contêiner com um navegador para uma estrutura de teste

Automação do teste de ponta a ponta de um sistema de informação integrado
Parte 2-2. Implementando o processo de upload de um arquivo de um contêiner com um navegador para uma estrutura de teste. Pesquise o nome do arquivo baixado pelo navegador


Autor: habr.com/us/users/anrad
Hubs:
Tags: #autotest, #selenium, #selenoid, #headlessbrowser, #download


Quando desenvolvíamos autotestes de ponta a ponta para a interface do usuário, fomos confrontados com a pergunta “Como obter o nome do último carregado navegador de arquivos do WebDriver? ”, o Google não recebeu nada rapidamente. Portanto, escrevi este artigo, que ao mesmo tempo dizia o que exatamente tínhamos um problema e como o resolvíamos.

Com este artigo, continuamos uma série de publicações sobre como automatizamos o processo de teste manual (doravante referido como autoteste) de um grande sistema de informação (doravante referido como Sistemas) em um dos grandes projetos LANIT e o que aconteceu com ele.

imagem
fonte


O artigo em si completa o ciclo; abaixo, há um link para todas as partes anteriores:
Parte 1. Organizacional e gerencial. Por que precisamos de automação. Organização do processo de desenvolvimento e gerenciamento. Organização de uso
Parte 2. Técnico. Arquitetura e pilha técnica. Detalhes da implementação e surpresas técnicas
Parte 2-1. Implementação da classe base para todos os testes e o JUnit RuleChain

Isso foi há um ano. Então, hoje, isso pode não ser relevante. Escreva nos comentários se você souber uma maneira eficiente de processar arquivos com vários servidores de grade selenoide.

Ao desenvolver “autotestes”, tivemos a tarefa de baixar (baixar) arquivos do sistema com uma análise subsequente de seu conteúdo. Para "fazer upload" de arquivos do sistema testado, usamos as seguintes soluções:
  • para o modo de inicialização "local" (inicie diretamente no PC em funcionamento) - quando o navegador "local" é inicializado, o nome da pasta local temporária é passado a ele como parâmetro. Em seguida, o arquivo é lido diretamente da pasta local para posterior análise;
  • para o modo "remoto" (via Bamboo) - o arquivo foi "obtido" do contêiner com o navegador através do recurso do servidor Solenoid: selenoid-host.example.com : 4444 / download / {SESSION_ID} / {FILE_NAME}


Os detalhes estão descritos na documentação.

Nos dois modos, para acessar o arquivo, você precisava saber o nome dele. Isso foi uma surpresa. O problema da falta de dados no nome do arquivo "download" era o seguinte:
  • depois de “clicar” no botão “baixar arquivo”, o navegador baixou o arquivo para a pasta local apropriada no contêiner;
  • nesse caso, o nome do arquivo foi formado dinamicamente e, como determiná-lo com antecedência, não conseguimos encontrar. Esta foi uma característica do nosso sistema de teste;
  • Além disso, esse arquivo deve ser "retirado" do contêiner e a verificação comercial de seu conteúdo deve ser realizada;
  • para "retirar" o arquivo, você deve saber seu nome, mas não o conhecíamos, pois o nome foi gerado dinamicamente e não havia valor no link.


Além disso, a situação foi agravada pelo fato de que, devido à grande complexidade de alguns testes, vários arquivos podem ser descarregados durante o teste como parte de diferentes scripts de teste independentes da composição do próprio teste.
A melhor solução para nós foi o método em que determinamos o último arquivo baixado. Havia várias maneiras de fazer isso:
  • . . , ;
  • Google Chrome javascript chrome://downloads/, html-. .




Analisar a composição dos arquivos carregados pelo navegador para o modo local é uma tarefa trivial.
No modo remoto, você precisa usar o recurso “não documentado” do servidor selenoid: selenoid-host.example.com : 4444 / download / {SESSION_ID} exibe uma lista de todos os arquivos baixados com êxito, em que SESSION_ID é um ID de sessão selenoide.
Em geral, o esquema funciona bem com uma exceção: nós Você precisa esperar um pouco até que o arquivo seja baixado e apareça na lista. A espera pode ser definida através de um ciclo de tempo limite, no entanto, dessa forma, não podemos obter informações sobre um possível erro de upload de arquivo. Só podemos determinar que o arquivo não foi carregado neste circuito. Portanto, no final, decidimos pelo método de determinar o nome do arquivo através do chrome: // downloads / page.

Obtendo o nome do arquivo através do chrome: // downloads / página


Este método funciona igualmente bem no modo local e remoto. O esquema do trabalho é bastante simples:
  • execute o script java para abrir a janela do chrome: // downloads /;
  • processar dados na janela da maneira usual. Aguarde até o primeiro arquivo da lista ser carregado e determine seu nome;
  • feche o chrome: // downloads / window e retorne o nome do arquivo que você está procurando.


Pesquisamos a ideia de usar o chrome: // downloads / e, infelizmente, não posso fornecer um link para a fonte, pois ela não foi preservada. A implementação real da classe para obter o nome do arquivo é fornecida abaixo.

Classe para obter o nome do arquivo baixado via chrome: // downloads /
	private static final long DOWNLOADS_PAGE_LOAD_TIMEOUT = 5_000;
	private static final long MAX_GET_FILE_NAME_ATTEMPT = 5;
 
	public static String getLastDownloadedFilename() throws DownloaderException {
        String[] filename = new String[1];
        Exception[] ex = new Exception[1];
        WebDriver driver = WebDriverRunner.getWebDriver();
        JavascriptExecutor executor = (JavascriptExecutor) driver;
        Utils.driver.openNewTabCheckAndClose(
                () -> {
                    executor.executeScript("window.open('','_blank');");
                },
                () -> {
                    driver.get("chrome://downloads/");
 
                    for (int i = 0; i < MAX_GET_FILE_NAME_ATTEMPT; i++) {
                    	ex[0] = null;
                        sleep();
                    	try {
                        	WebElement element = (WebElement) executor.executeScript(
                                    "return document.querySelector('downloads-manager').shadowRoot.querySelector('downloads-item').shadowRoot.getElementById('file-link')");
                        	filename[0] = element.getText();
                            LOGGER.info("Attempt get file name " + i + ". Name = '" + filename[0] + "'");
                    	} catch (WebDriverException e) {
                        	ex[0] = e;
                            LOGGER.info("Failed attempt "+ i + " to get filename text: " + e.getMessage());
                        	continue;
                    	}
                    	if (filename[0] != null && !filename[0].isEmpty()) {
                        	 //             
                         	executor.executeScript(
                                    "document.querySelector('downloads-manager').shadowRoot.querySelector('downloads-item').shadowRoot.getElementById('remove').click()");
                        	break;
                    	}
                    }
                }
    	);
 
    	if (filename[0] != null && !filename[0].isEmpty()) {
            return filename[0];
    	}
 
    	String message = "Timeout. Can not get last downloaded file name from chrome://downloads/. File name is '" + filename[0] + "'. Exception: " + ex[0].getMessage();
        LOGGER.warning(message);
    	throw new DownloaderException(message, ex[0]);
	}

All Articles