Fonte: https://medium.com/bytebytego-system-design-alliance/system-design-blueprint-the-ultimate-guide-e27b914bf8f1
Fonte: https://medium.com/bytebytego-system-design-alliance/system-design-blueprint-the-ultimate-guide-e27b914bf8f1
Most of these courses also answer questions I have shared here.
Fonte: https://dev.to/somadevtoo/top-3-strategies-for-scaling-microservices-architecture-1m46
A Comprehensive Guide to TestNG: Mastering Test Automation in Java
In the world of software testing and automation, TestNG has emerged as one of the most powerful and widely adopted testing frameworks for Java. Its versatility, rich features, and simplicity make it a go-to tool for developers and QA engineers alike. Whether you’re just starting out with automated testing or looking to optimize your current workflow, this in-depth post will help you master TestNG and use it effectively in your projects.
TestNG (Test Next Generation) is a popular Java testing framework inspired by JUnit but with enhanced functionalities. It was designed to address the shortcomings of older testing frameworks by providing additional features, such as:
TestNG is well-suited for unit testing, integration testing, functional testing, end-to-end testing, and even large-scale test automation suites.
TestNG offers a wide range of features, including:
With TestNG, you get built-in test execution reports that can be further customized to fit your needs. Integration with tools like ReportNG or ExtentReports takes reporting to the next level.
TestNG’s ability to run tests in parallel and its suite-based execution model make it ideal for large-scale testing projects.
TestNG works seamlessly with:
To begin using TestNG, you need to set up your project with the necessary dependencies and configurations.
If you’re using Maven, add the following dependency to your pom.xml
file:
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.8.0</version> <!-- Use the latest version -->
<scope>test</scope>
</dependency>
For Gradle, add the dependency in your build.gradle
file:
testImplementation 'org.testng:testng:7.8.0'
Here is a simple example of a TestNG test class:
import org.testng.annotations.Test;
import org.testng.Assert;
public class ExampleTest {
@Test
public void testAddition() {
int result = 5 + 3;
Assert.assertEquals(result, 8, "Addition result is incorrect");
}
@Test
public void testSubtraction() {
int result = 10 - 5;
Assert.assertEquals(result, 5, "Subtraction result is incorrect");
}
}
You can execute your TestNG tests using your IDE (Eclipse, IntelliJ, etc.) or build tools like Maven. TestNG generates a detailed HTML report after the execution.
To run the tests via Maven, use:
mvn test
Annotations are the backbone of TestNG. They help manage the lifecycle and execution flow of tests. Below are the most commonly used annotations:
Annotation | Description |
---|---|
@Test |
Marks a method as a test case. |
@BeforeMethod |
Executes before each test method. |
@AfterMethod |
Executes after each test method. |
@BeforeClass |
Executes once before all test methods in a class. |
@AfterClass |
Executes once after all test methods in a class. |
@BeforeSuite |
Executes before the entire test suite runs. |
@AfterSuite |
Executes after the entire test suite completes. |
@DataProvider |
Supplies test data for data-driven testing. |
@Parameters |
Passes parameters to test methods. |
@BeforeMethod
and @AfterMethod
import org.testng.annotations.*;
public class TestLifecycle {
@BeforeMethod
public void beforeMethod() {
System.out.println("Executing Before Method");
}
@Test
public void testExample() {
System.out.println("Executing Test Method");
}
@AfterMethod
public void afterMethod() {
System.out.println("Executing After Method");
}
}
Output:
Executing Before Method
Executing Test Method
Executing After Method
TestNG allows you to prioritize test methods using the priority
attribute in the @Test
annotation.
@Test(priority = 1)
public void testLogin() {
System.out.println("Login Test");
}
@Test(priority = 2)
public void testDashboard() {
System.out.println("Dashboard Test");
}
@DataProvider
@Test(dataProvider = "loginData")
public void testLogin(String username, String password) {
System.out.println("Username: " + username + ", Password: " + password);
}
@DataProvider(name = "loginData")
public Object[][] getData() {
return new Object[][] {
{"user1", "pass1"},
{"user2", "pass2"}
};
}
Parallel execution improves performance by running tests concurrently. Use the parallel
attribute in the TestNG XML configuration file:
<suite name="ParallelSuite" parallel="methods" thread-count="2">
<test name="Test1">
<classes>
<class name="com.example.ParallelTests"/>
</classes>
</test>
</suite>
TestNG integrates seamlessly with Selenium WebDriver for web automation testing. Here’s an example of running a Selenium test using TestNG:
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
public class SeleniumTest {
@Test
public void openGoogle() {
System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
WebDriver driver = new ChromeDriver();
driver.get("https://www.google.com");
System.out.println("Title: " + driver.getTitle());
driver.quit();
}
}
TestNG is a powerful and versatile testing framework that simplifies the testing process for Java applications. With its advanced features, annotations, and integration capabilities, it caters to the needs of both small projects and large-scale enterprise solutions. By leveraging TestNG’s full potential, you can write cleaner, more efficient, and maintainable test code.
Neste post, abordaremos as principais classes de mapas disponíveis na linguagem Java, detalhando suas características, vantagens e desvantagens, performance e melhores práticas. As classes discutidas incluem HashMap, TreeMap, LinkedHashMap, Hashtable, ConcurrentHashMap e EnumMap.
Map
.hashCode()
corretamenteCollections.synchronizedMap()
ou ConcurrentHashMap
em ambientes multithreaded.NavigableMap
.firstKey()
, lastKey()
, etc.As diferentes implementações da interface Map
em Java oferecem flexibilidade e eficiência na manipulação de dados. A escolha entre elas deve ser baseada nas necessidades específicas da aplicação, considerando fatores como desempenho, segurança em ambientes multithreaded e requisitos de ordenação. Ao seguir as melhores práticas discutidas neste eBook, você poderá otimizar o uso dessas estruturas em seus projetos Java.
É muito comum que, ao desenvolver um software, alguns desafios acabem surgindo no meio do caminho. No entanto, conforme é possível adquirir experiência ao longo do tempo, torna-se mais fácil determinar quais problemas são mais recorrentes, mesmo que em projetos inteiramente diferentes. Por isso, o Design Patterns é indispensável.
Os padrões que podem ser identificados com a prática levam o nome de “Padrões de Projetos”. Ao nos familiarizarmos com eles, o desenvolvimento de determinados sistemas acaba se tornando muito mais fácil do que era esperado e a chance de acerto é ainda maior.
Com a aplicação do Design Patterns, fica ainda mais fácil conseguir alcançar resultados satisfatórios e que não tragam problemas a curto ou a longo prazo para o seu projeto. É por isso que, neste artigo, você poderá encontrar:
Dentro da área de desenvolvimento de software, os Design Patterns são padrões de projetos que podem ser vistos como uma solução geral, atribuindo maior segurança aos programadores e programadoras. Geralmente, eles são aplicados em alguns problemas específicos que ocorrem ao longo da montagem da estrutura de um software ainda em andamento.
É válido ressaltar que esse tipo de projeto não é aplicado em qualquer parte do código da programação e não pode ser utilizado com a famosa fórmula “Ctrl + c/ Ctrl + v”. Ele deve ser visto como um modelo a se seguir para que um determinado problema seja resolvido em alguma situação específica.
Os Design Patterns são a melhor maneira de solucionar problemas comuns por meio de uma pessoa programadora da área de TI, principalmente quando é necessário projetar as peças de um software em uma determinada aplicação ou sistema. Os padrões são capazes de implicar a orientação dos objetos constituintes do programa desenvolvido ou seu estado mutável.
Sabendo o que é Design Patterns, fica muito mais fácil para que a pessoa consiga sair de uma situação incômoda e passe a enxergar os seus projetos de desenvolvimento com muito mais flexibilidade e facilidade.
Entre os anos de 1977 e 1979, o arquiteto Christopher Alexander escreveu, em seus livros (Notes on the Synthesis of Form, The Timeless Way of Building e A Pattern Language), um padrão que precisa ter, dentro de um ideal, algumas características. São elas:
Retomando a história dos Design Patterns, no ano de 1987, dois programadores (Kent Beck e Ward Cunningham) dispuseram os primeiros padrões de projeto para a área voltada à ciência da computação. Dessa maneira, conseguiram apresentar alguns padrões capazes de construir as aplicações comerciais dentro da linguagem Smalltalk.
Ainda assim, a força dos padrões só chegou a ganhar popularidade no ano de 1995, quando o livro Design Patterns: Elements of Reusable Object-Oriented Software foi publicado. Os autores ficaram conhecidos como “Gangue dos Quatro” e, após esse incentivo, muitas outras obras foram lançadas a respeito.
Além das características que se aplicam aos padrões, Alexander também definiu alguns formatos para que a descrição de um padrão pudesse ter. Dessa maneira, foi possível facilitar o trabalho de muitas pessoas desenvolvedoras e, ainda por cima, permitir que elas tivessem mais sucesso nos trabalhos que desejavam iniciar.
Essas descrições tinham como base os seguintes conceitos:
Agora que já é possível saber o que é Design Patterns, está na hora de compreender como ele funciona na prática e como pode ser de grande ajuda na hora de compor um software. Ainda que possa parecer uma fórmula pronta, esses padrões estão mais para pequenas saídas para problemas corriqueiros no sistema.
Em boa parte dos casos, ele é visto como uma solução reutilizável para os problemas que aparecem no seu sistema, mas precisam estar dentro de um contexto único. Eles servem como um guia para o programador ou programadora, permitindo que o tempo não seja perdido em um determinado tópico, resolvendo-o o mais rápido possível.
Em resumo, eles são utilizados dentro do processo de criação de um software ou programa, visando melhorar a sua qualidade e, ainda por cima, fazer com que a pessoa responsável tenha muito mais tempo para focar em partes relevantes do seu projeto. Assim, é possível deixar de lado os pequenos erros que poderiam atrapalhar a funcionalidade.
De uma maneira geral, os Design Patterns servem como uma boa referência para aqueles e aquelas que estão começando agora ou, simplesmente, desejam ter mais facilidade na criação de seu trabalho. Podem ser usados a qualquer momento, desde que a pessoa compreenda bem onde encaixá-los e quando incluí-los.
O Gang Of Four Design Patterns foi criado por 4 autores, sendo eles Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides. Esse padrão de design foi apresentado, pela primeira vez, no livro “Design Patterns: Elements of Reusable Object-Oriented Software”, no ano de 1994. Por meio dele, é possível ter uma base de padrões do campo de design para objetos.
O padrão de design nada mais é do que aquela solução que, em algum momento, será reutilizada para resolver um problema que é comumente encontrado em um software. Dessa forma, sempre que for necessário, haverá um modelo disponibilizado para burlar algum empecilho na programação.
Os padrões de design Gang Of Four Design Patterns são seguidos por algumas categorias que, logo abaixo, serão definidas, facilitando a vida de quem programa. Sendo assim, aproveite para aprender um pouco mais e desenvolver maior desenvoltura acerca do tema.
O Creational Design Patterns, em tradução livre “Design Patterns de Criação” é um padrão de criação que precisa lidar com a criação de objetos. Sendo assim, será necessário encontrar maneiras de resolver os problemas de design decorrentes da criação de algum objeto.
De uma maneira geral, este padrão de Design Patterns tem como principal objetivo construir o objeto e sua referência. Além disso, o grupo se mostra inteiramente relevante para sustentar o princípio que é considerado essencial, referindo-se à programação de uma interface e não de suas implementações.
Neste padrão, é possível encontrar:
No design de estrutura, será necessário utilizar os padrões estruturais com o principal objetivo de facilitar a finalização do projeto. Por meio dele, será possível identificar uma maneira bem mais simples de realizar os relacionamentos entre entidades sem necessariamente se deparar com algum erro no meio do caminho.
Outro ponto importante, que pode ser facilmente observado por quem estuda sobre Design Patterns, é que essa categoria trata da relação direta entre os objetos e como eles interagem entre si, visando formar um objeto maior e mais complexo.
Este padrão é composto por:
Por fim, ainda há o Design Patterns de Comportamento, muito utilizado para definir padrões comportamentais. Por meio desse tipo de produção, é possível identificar padrões de comunicação que são comuns entre objetos e que podem ser capazes de dar continuidade aos padrões anteriormente estabelecidos.
Além disso, eles ainda são responsáveis por uma comunicação direta entre os objetos, principalmente no que diz respeito aos termos de responsabilidade e de algoritmo.
Neste padrão, estão inseridos:
É importante relatar que o conceito de padrão de um projeto foi criado por volta dos anos 70, pelo arquiteto Christopher Alexander, como já mencionado anteriormente. Por meio de seus conhecimentos acumulados em uma mesma obra, foi possível estabelecer alguns padrões a serem seguidos pelas pessoas programadoras.
Além do Design Patterns Gang Of Four, também é possível encontrar outros tipos como, por exemplo, o Car Connection, Positive Outdoor e o Connected Buildings. São tantos os modelos que, quando colocados lado a lado, é possível somar mais de 125 padrões. Por um lado, é benéfico para quem programa, já que podem ter mais opções na hora de resolver algum problema de software.
No entanto, quando qualquer tipo de padrão referido se relaciona com o GOF (Gang Of FOur), é válido lembrar que ele atende a um formato específico, sendo ele:
Para quem está iniciando no âmbito do Design Patterns, é importante levar em consideração que esse tipo de aplicação pode ser bastante desafiadora em seus princípios, além de apresentar um desenvolvimento de software um pouco mais complexo do que aquele que foi aprendido anteriormente. Sendo assim, é necessário estar atento a todos os detalhes.
Mesmo que não exista uma técnica muito simples para se inserir nesse mundo tecnológico dos códigos, é necessário ressaltar que algumas dicas podem ser suficientes para reduzir a carga de trabalho. Ainda assim, para quem deseja seguir nesse caminho, qualquer pequeno esforço é válido.
É muito comum que os iniciantes acreditem que todo aplicativo precisa usar padrões de um determinado projeto. No entanto, é importante lembrar que isso não é necessário. Ainda que os padrões sejam muito úteis para solucionar problemas conhecidos, é preciso entender que usá-los acrescenta certa complexidade ao trabalho.
Sendo assim, caso um programador ou programadora esteja escrevendo um projeto pequeno, levando em consideração um script que será usado em apenas uma situação não crítica, aplicar padrões de projeto pode acabar se tornando um verdadeiro exagero e, consequentemente, uma perda de tempo.
Mais um erro cometido por iniciantes quando o assunto é Design Patterns está diretamente relacionado com utilizar vários padrões dentro de um único projeto. Isso não só aumentará a complexidade do desenvolvimento do software como também poderá acrescentar alguns erros que, posteriormente, precisarão ser resolvidos.
Sendo assim, a melhor dica é tentar desenvolver o hábito de identificar determinados padrões que podem ser usados dentro de um mesmo sistema. Assim, será fácil perceber que será preciso usar mais alguns padrões do que outros. Por isso, alguns padrões se tornarão os seus favoritos e mais corriqueiros no projeto.
Para trabalhar com o Design Patterns, é necessário ter muita paciência. Cada passo dado representa uma nova experiência vivida. Por meio do GOF, será possível assimilar muitas coisas e, consequentemente, adquirir desenvoltura para conseguir finalizar os seus projetos sem, necessariamente, realizar tantas consultas a ele.
Ter em mente todos os padrões estabelecidos no Design Patterns pode acabar se mostrando um processo gradual e um tanto lento, além de ser contínuo. Por isso, é importante que, antes de mais nada, a pessoa possa se sentir à vontade com os padrões GOF para que, em seguida, comece a usar padrões do catálogo P do EAA.
Assim como tudo na vida, o aprendizado vem com o treinamento. É por isso que, se você deseja se aprofundar no Design Patterns, precisará reservar um bom tempo do seu dia para exercitar os códigos e padrões pré-estabelecidos. Lembrar padrões não acontecerá de uma hora para a outra.
Uma boa dica de exercício é começar a criar dicas práticas para os padrões utilizados em um projeto. Depois, basta anotá-las com a ajuda de alguma figura ou palavra-chave. Assim, ficará muito mais fácil memorizar os padrões e todos os conceitos que estão atrás dele.
Existem muitos profissionais que já estão formalmente acostumados com a utilização do Design Patterns. Sendo assim, é necessário buscá-los caso você também queira se especializar e sair da categoria de iniciante para especialista. Estudar o código escrito por alguém com experiência é um bom primeiro passo.
Dessa forma, será possível compreender como os desenvolvedores ou desenvolvedoras estão aplicando os padrões e como você conseguirá aprender por meio de técnicas individuais. Existem muitos fóruns na internet sobre o assunto e, também, alguns cursos que podem ser muito bem aproveitados pelos programadores com sede de conhecimento.
É importante lembrar, principalmente para as pessoas que estão iniciando, que os princípios e padrões SOLID não serão úteis, apenas, durante o desenvolvimento inicial de sua base de código. Isso porque elas poderão se mostrar inteiramente úteis ao estender ou manter uma base de código que já existe.
É por isso que, para quem está se aperfeiçoando no Design Patterns, seja por conta própria ou com a ajuda de especialistas, precisa utilizar a manutenção de códigos como um dos pilares da programação. Adote boas práticas e comece a realizar exercícios diariamente para que, enfim, seja possível se tornar um especialista na área.
Um dos principais motivos para estudar esse tipo de Design está na facilidade que ele oferece. Certo dia, algumas pessoas começaram a perceber que tinham os mesmos problemas durante o processo de programação. Por isso, desenvolveram alguns padrões que fossem capazes de reverter a situação para tornar o projeto mais assertivo.
Ainda que os padrões do Design Patterns GOF tenham sido escritos há algumas décadas, aprender cada vez mais sobre os softwares é extremamente importante. Isso porque os sistemas costumam funcionar como se, de fato, fossem organismos vivos. Por isso, para ser um bom programador ou uma boa programadora, é preciso acompanhar as transformações e se adaptar a elas.
É válido lembrar, também, que nem todos os padrões estabelecidos no GOF são bem aceitos dentro das comunidades de desenvolvimento. Por isso, abusar no uso de padrões dentro de um mesmo projeto pode acabar complicando ainda mais a situação. A supervalorização de qualquer coisa deixa a sua manutenção complexa.
Existem muitos benefícios que rondam a utilização dos Design Patterns, mas um deles, com toda a certeza, é o mais relevante: a agilidade. Para quem está desenvolvendo um projeto, códigos que possam ajudar a solucionar um problema rapidamente podem ser muito bem-vindos a qualquer momento.
Além disso, esses padrões determinados são ótimos para ajudar a organizar e manter os projetos em ordem. Eles se baseiam diretamente em um baixo acoplamento entre classes, além de levar em consideração a padronização estabelecida em um código. Cada dia mais surgem técnicas facilitadas para auxiliar o programador.
Depois de compreender melhor o que é Design Patterns, como ele funciona e porque é necessário aprender, é possível observar que esse padrão foi criado para facilitar a vida dos programadores e programadoras. Sendo assim, torna-se indispensável buscar conhecimento acerca da área para solucionar os problemas dos projetos de forma simples, assertiva e ágil.
Os princípios S.O.L.I.D. são um conjunto de diretrizes para o design de software orientado a objetos que ajudam a fazer sistemas mais compreensíveis, flexíveis e mantíveis. Criados e popularizados por Robert C. Martin (também conhecido como “Uncle Bob”), esses princípios têm como objetivo melhorar a legibilidade do código, facilitar a manutenção e permitir que o software evolua com menos riscos de introduzir bugs. Este eBook explora cada um dos princípios com detalhes, auxiliando desenvolvedores a aplicá-los efetivamente em projetos sem recorrer a exemplos de código.
O Princípio da Responsabilidade Única estabelece que uma classe deve ter uma, e somente uma, razão para mudar. Isso significa que cada classe deve ser responsável por uma única parte da funcionalidade fornecida pelo software. A ideia central é que acoplar múltiplas responsabilidades em uma única classe aumenta o risco de alterações em uma área afetarem outras, levando a bugs e dificuldades na manutenção.
O Princípio do Aberto/Fechado declara que o software deve ser aberto para extensão, mas fechado para modificação. Isso significa que a funcionalidade de uma classe deve ser estendida sem alterar seu código existente, promovendo a criação de sistemas que podem crescer com o tempo sem sacrificar estabilidade.
Segundo o Princípio da Substituição de Liskov, objetos de uma classe devem poder ser substituídos por objetos de suas subclasses, sem alterar a correção do programa. Este princípio assegura que uma classe derivada pode ser usada no lugar de sua classe base sem comprometer a funcionalidade.
O Princípio da Segregação de Interface sugere que os clientes não devem ser forçados a depender de interfaces que não utilizam. Isso implica que é melhor criar interfaces mais específicas e focadas, ao invés de usar interfaces “gordas” e genéricas.
O Princípio da Inversão de Dependência afirma que módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações, que não devem depender de detalhes. Este princípio incentiva o uso de interfaces ou classes abstratas para desacoplar componentes do sistema.
Os princípios S.O.L.I.D. são fundamentais para a construção de software robusto, escalável e fácil de manter. Ao aplicar esses princípios, os desenvolvedores podem criar sistemas mais modulares e adaptáveis às mudanças, garantindo que os investimentos em software sejam protegidos ao longo do tempo. Em um cenário de desenvolvimento contínuo, onde mudanças e requisitos novos são constantes, compreender e aplicar S.O.L.I.D. é essencial para garantir a longevidade e o sucesso dos projetos de software.
Para aprofundar seu conhecimento e aplicar eficazmente os princípios S.O.L.I.D., considere as seguintes ações:
Espero que este eBook sirva como um guia útil e inspirador em sua jornada no desenvolvimento de software de alta qualidade!
Livro: “Design Patterns: Elements of Reusable Object-Oriented Software” Autores: Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides Publicado em 1994
Os padrões de design visam tornar o código mais flexível, reutilizável e manutenível, resolvendo problemas recorrentes no desenvolvimento de software orientado a objetos.
What’s top 5 books that cover test coding algorithms?
Here are five highly regarded books on coding algorithms and techniques for mastering technical interviews and test coding:
Each of these books caters to different learning styles and needs. If you’re preparing for interviews, start with Cracking the Coding Interview or Elements of Programming Interviews. For deeper theoretical knowledge, go with CLRS or Skiena.
Here are five highly recommended books that cover coding algorithms, ideal for those looking to enhance their understanding and skills in algorithmic problem-solving:
These books not only cover algorithmic concepts but also provide practical insights into coding practices that can significantly improve your programming capabilities.
Here are five highly recommended books for learning about testing and coding algorithms:
Each of these books offers a unique perspective on algorithms and testing, providing readers with a well-rounded understanding of how to develop, implement, and verify algorithmic solutions. They range from practical interview preparation to deep theoretical understanding, catering to different levels of expertise and learning styles.
For those seriously interested in mastering algorithm design and testing, I recommend reading multiple books from this list, as each provides complementary insights into writing efficient, correct, and testable code.