Sobes.tech
Middle

Onde na automação de testes pode-se aplicar o padrão de projeto Singleton?

sobes.tech IA

Resposta da IA

No teste automatizado, Singleton é frequentemente utilizado para gerir recursos que devem ser instâncias únicas durante toda a sessão de teste.

Exemplos de uso:

  • Gestão do WebDriver: Para garantir uma única instância do objeto WebDriver, utilizado por todas as classes de teste. Isto evita abrir/fechar o navegador repetidamente e mantém o estado entre os passos do teste.

    public class WebDriverSingleton {
        private static WebDriver instance;
    
        private WebDriverSingleton() {
            // Construtor privado para evitar criação de instâncias
        }
    
        public static WebDriver getInstance() {
            if (instance == null) {
                // Inicialização do WebDriver (por exemplo, Chrome, Firefox)
                instance = new ChromeDriver();
            }
            return instance;
        }
    
        public static void quitDriver() {
            if (instance != null) {
                instance.quit();
                instance = null;
            }
        }
    }
    
    // Uso na classe de teste
    public class MyTests {
        @BeforeClass
        public void setup() {
            WebDriver driver = WebDriverSingleton.getInstance();
            // Uso do driver
        }
    
        @AfterClass
        public void tearDown() {
            WebDriverSingleton.quitDriver();
        }
        // Métodos de teste
    }
    
  • Gestão de conexão à base de dados: Garante que exista apenas uma conexão ativa à base de dados para realizar pré-condições de teste ou verificações de dados.

    public class DatabaseConnection {
        private static Connection instance;
    
        private DatabaseConnection() {
            // Construtor privado
        }
    
        public static Connection getInstance() {
            if (instance == null) {
                try {
                    // Estabelecer conexão com a base de dados
                    instance = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb", "user", "password");
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            return instance;
        }
    
        public static void closeConnection() {
            if (instance != null) {
                try {
                    instance.close();
                    instance = null;
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
  • Gestão do arquivo de configuração: Carregamento dos parâmetros de configuração a partir de um arquivo no início da execução do teste e fornecimento de acesso único a eles.

    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
    
    public class ConfigurationManager {
        private static ConfigurationManager instance;
        private Properties properties;
    
        private ConfigurationManager() {
            properties = new Properties();
            try (InputStream input = getClass().getClassLoader().getResourceAsStream("config.properties")) {
                if (input == null) {
                    System.out.println("Desculpe, não foi possível encontrar config.properties");
                    return;
                }
                properties.load(input);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    
        public static ConfigurationManager getInstance() {
            if (instance == null) {
                instance = new ConfigurationManager();
            }
            return instance;
        }
    
        public String getProperty(String key) {
            return properties.getProperty(key);
        }
    }
    
  • Gestão do registo: Uma única instância do registo para a gestão centralizada dos logs de execução do teste.

O uso de Singleton ajuda a gerir recursos que requerem unicidade, mas deve-se ter cuidado com seu uso, especialmente em frameworks de teste multithread, onde podem surgir problemas de acesso concorrente e necessidade de sincronização. Nesses casos, abordagens mais complexas, como o uso de ThreadLocal, podem ser necessárias.