DEV Community

Cover image for Lidando com regressão visual: enfrentando desafios com Django, Selenium e Pillow
Eduardo Oliveira
Eduardo Oliveira

Posted on

Lidando com regressão visual: enfrentando desafios com Django, Selenium e Pillow

O django-image-uploader-widget é um projeto de componente de upload de imagem para o django. Por motivos de retrocompatibilidade entre as versões 3.x e 4.x do django, foi decidido implementar testes de regressão visual utilizando Selenium e Pillow. Nesse texto vamos trabalhar esse tema e seus desafios.

Índice

Introdução

O django-image-uploader-widget é um projeto de componente de upload de imagem para o django, criado para melhorar a estética dos uploaders originais. É mantido como open-source desde o início, inclusive recebendo colaborações de outros desenvolvedores.

Visualização do Componente

Com o lançamento das versões 4.x do django, o componente passou a ter diferenças significativas no visual entre algumas de suas versões, conforme registrado na issue #96.

A partir dessa diferença visual, em diferentes versões do django, entra no radar do projeto a possibilidade de implementação de testes de regressão visual. Nesse artigo vamos explorar os desafios enfrentados durante essa implementação.

O suporte do django a suas versões

Um ponto que vale ser levado em consideração, para justificar a decisão de implementar testes de regressão visual, é o fato de que o django mantem, por muito tempo, suporte a diversas de suas versões (Ver Referência), como na imagem:

django supported versions roadmap

O que é um teste de regressão visual?

Como o Guilherme Ananias comenta no seu texto (Ver Referência), um teste de regressão visual é um tipo de teste que irá garantir que qualquer alteração no código não irá alterar a forma como o usuário final irá verá esse componente ou página.

Dado o contexto de suporte a múltiplas versões do django e, principalmente, do django-admin, com alterações de estilização entre as versões, esse tipo de teste pode, também, ser utilizado para garantir retrocompatibilidade entre o componente e as versões do django.

O Browser e o Selenium

O código desse componente já possuía uma suite de testes, funcionais, rodando com o Selenium e o Chrome Driver. A justificativa para o uso de testes funcionais pode ser lida nas documentações do projeto.

Tendo o browser e, mais especificamente, o selenium disponíveis, é possível utilizar o método screenshot(filename) para salvar um screenshot de um elemento da página, conforme documentação.

Pillow

A utilização dos campos de imagem do django só é possível com a biblioteca Pillow instalada no projeto. Essa biblioteca traz, com a sua instalação, métodos para lidar com a diferença entre imagens (Ver Referência).

Juntando as Peças

Ao utilizar o selenium e a lib Pillow é possível, de forma bem simples, tirar screenshot dos elementos e comparar com outro screenshot já armazenado (ver implementação).

Desafios

Foram enfrentados diversos desafios durante a implementação dos testes de regressão visual. Alguns desses desafios foram causados pela natureza das escolhas para a implementação desses testes e outros pela natureza do django e django-admin.

O problema inicial

Toda a implementação dos testes de regressão visual nasceram devido a um problema entre versões do django, vide #96, onde, devido a alteração de estilos do django-admin, adicionando flexbox, causou a quebra da estilização.

Assim, é necessário dizer que um dos primeiros desafios é da natureza do django e, principalmente, do suporte a múltiplas versões do mesmo.

A solução, pra esse caso, em específico, foi simples e corriqueira fazendo o tratamento tanto pro css das versões 3.x do django-admin quanto para as novas, que utilizam flexbox.

Alteração nas fontes

Complementando o problema inicial, logo nos primeiros testes, foi identificado uma alteração no padrão visual do componente (ou widget), em uma das versões mais recentes do django. As fontes do widget estavam diferentes. Ao buscar pelas releases notes do django, é observado a seguinte descrição (referência):

The admin’s font stack now prefers system UI fonts and no longer requires downloading fonts. Additionally, CSS variables are available to more easily override the default font families.

Uma solução, não necessariamente a melhor, porém a mais simples foi a de adiantar essa alteração das fontes, para o componente de upload de imagens, independente da versão do django.

Animações, transições e threshold

Da natureza da comparação das imagens, junto ao fato de ser uma aplicação web executando, tem-se o problema de ter alguns pixeis de diferença em algumas situações, provavelmente causado por animações e transições.

Para aguardar o fim das transições e animações, o método time.sleep() do Python foi utilizado. Por conta da utilização do time.sleep() é, natural, que o tempo de execução dos testes aumente significativamente.

Nesse ponto, é sempre importante deixar pontuado que, não existe certo ou errado, ou solução pra todos os problemas, ou, ainda, solução sem contrapontos. Toda técnica, ou escolha, geralmente, tem suas vantagens e desvantagens. Cabe ponderar se as vantagens superam as desvantagens no contexto ao qual se quer utilizar a ferramenta.

Por fim, após a implementação do time.sleep() raras se tornaram as vezes que as imagens divergiam em locais que não deveriam, porém, por garantia, ainda foi implementado um sistema de comparação com threshold (limiar) para esses casos.

Theme Toggle

Ainda nas release notes da versão 4.2 do django é possível verificar a adição de um theme toggle no admin. Quando o componente foi, inicialmente, desenvolvido, as versões 4.x do django ainda não tinham assumido o status de LTS. Além disso, por um tempo, apenas as manutenções básicas foram dadas ao projeto. Dados esses contextos, o componente não tinha suporte a mudança de tema pela interface de usuário.

Esse problema só foi percebido, de fato, com a implementação dos testes de regressão visual e, para a solução, foi aberta uma nova issue no GitHub (#103).

Esse foi o único caso em que foi implementada uma condicional da versão do django em que os testes estavam sendo executados:

import django
# ...

class InlineEditorUIRegressionTestCase(IUWTestCase):
    # ...
    def test_ui_initialized_toggle_dark_theme_inverted(self):
        self.dark_mode()

        major, minor, _, _, _ = django.VERSION
        if major < 4 or minor < 2:
            return
Enter fullscreen mode Exit fullscreen mode

Referências

As referências citadas no texto, listadas:


Foto de Budka Damdinsuren na Unsplash

Top comments (2)

Collapse
 
cherryramatis profile image
Cherry Ramatis

Foda demais primo!!!

Collapse
 
eduardojm profile image
Eduardo Oliveira

Obrigadoooo