Este repositório inclui o código-fonte de um projeto de prova de conceito destinado a avaliar a acessibilidade de projetos da web. O projeto utiliza tecnologias como .NET 6, o framework de teste NUnit, Selenium e AxeCore.
- .NET 6
- NUnit
- Deque.AxeCore.Selenium
- Selenium.WebDriver
- Selenium IDE
O AxeCore é uma ferramenta de código aberto que permite avaliar a acessibilidade de projetos da web. Está disponível para diversas linguagens como csharp, Java, Python, Ruby, JavaScript, etc. Para mais informações sobre o AxeCore, basta acessar o (repositório oficial) no GitHub.
Nesse exemplo foi utilizada a biblioteca Deque.AxeCore.Selenium
. Essa biblioteca permite a integração do AxeCore com o Selenium WebDriver, facilitando assim a utilização dos comandos de analisador de acessibilidade.
AxeResult axeResult = new AxeBuilder(WebDriver).Analyze();
Para instalar o Deque.AxeCore.Selenium, basta acessar o (site oficial) e seguir as instruções de instalação.
O Selenium WebDriver é uma ferramenta de código aberto que permite automatizar ações em navegadores web. Ele está disponível para diversas linguagens como csharp, Java, Python, Ruby, JavaScript, etc. Para instalar o Selenium WebDriver, basta acessar o (site oficial) e seguir as instruções de instalação para a linguagem escolhida.
Para automatizar a navegação no site escolhido, foi utilizado o Selenium IDE. O Selenium IDE é uma ferramenta de código aberto que permite gravar e reproduzir testes no navegador. O Selenium IDE é uma extensão do navegador que funciona no Google Chrome e no Firefox. Para instalar o Selenium IDE, basta acessar o site oficial (Google Chrome ou Firefox)e seguir as instruções de instalação.
Para gravar um teste web, basta clicar no botão de gravação e navegar pelo site, o Selenium IDE irá gravar todas as ações realizadas no navegador. Para reproduzir o teste, basta clicar no botão de reprodução. O Selenium IDE irá reproduzir todas as ações gravadas no navegador.
Após a validação das ações realizadas é possível exportar o test, no nosso caso para o csharp nunit
. Para isso, basta clicar no botão de exportação e selecionar a linguagem de programação desejada.
Com o resultado do export na mão podemos utilizar o código gerado no nosso projeto de teste de acessibilidade.
Com a sequência abaixo é possível criar um projeto template inicial de teste com NUnit, Selenium e AxeCore.
- Crie um novo projeto de teste NUnit no Visual Studio ou usando o comando de linha de comando:
dotnet new nunit -n SeleniumTest
- Adicione as dependências do projeto:
dotnet add package Deque.AxeCore.Selenium
dotnet add package Selenium.WebDriver
dotnet add package Selenium.WebDriver.ChromeDriver
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.json
dotnet add package FluentAssertions
- Crie um arquivo de configuração chamado
appsettings.json
e adicione o seguinte conteúdo:
{
"TestSettings": {
"BaseUrl": "https://www4.fazenda.sp.gov.br/modelo_core_mvc"
}
}
- Adicione o seguinte trecho de código ao seu arquivo de projeto
.csproj
:
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
- Substitua o conteúdo do arquivo
UnitTest1.cs
pelo seguinte:
using Deque.AxeCore.Commons;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Deque.AxeCore.Selenium;
using FluentAssertions;
using Microsoft.Extensions.Configuration;
using System;
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using System.Net.Mail;
namespace SeleniumTest
{
public class SeleniumTests
{
private IWebDriver driver; // Instância do Selenium WebDriver
private IConfiguration configuration; // Instância do ConfigurationBuilder
private string baseURL; // URL base do site
[SetUp]
public void Setup()
{
// Carregar as configurações do arquivo appsettings.json
configuration = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json", false, false).Build();
baseURL = configuration["TestSettings:BaseUrl"];
// Configurar e personalizar o comportamento do Google Chrome
ChromeOptions options = new();
// Personalizar o comportamento do Google Chrome para o teste
options.AddArguments("--headless"); // Inicia o Chrome no modo headless, sem interface gráfica
options.AddArguments("--start-maximized"); // Abrir o navegador em tela cheia
options.AddArguments("--disable-infobars"); // Desativa as infobars
options.AddArguments("--disable-extensions"); // Desativa extensões
options.AddArguments("--disable-gpu"); // Desativa a aceleração de hardware somente para Windows
options.AddArguments("--disable-dev-shm-usage"); // Desativa o uso compartilhado de memória em /dev/shm
options.AddArguments("--no-sandbox"); // Bypass OS security model
driver = new ChromeDriver(options);
}
[TearDown]
public void TeardownTest()
{
// Verifica se a instância do WebDriver não é nula
if (driver != null)
{
// Tira uma captura de tela se o teste falhar
TakeScreenshot();
// Fecha o navegador e libera os recursos
driver.Quit();
driver.Dispose();
}
}
[Test]
public void AccessibilityTest_InitialPage()
{
// Executa o teste de acessibilidade na página inicial
Selenium_CheckInitialPage();
}
[Test]
public void AccessibilityTest_ProjectPage()
{
// Executa o teste de acessibilidade na página de projetos
Selenium_CheckProjectPage();
}
private void Selenium_CheckInitialPage()
{
// Navega até a página do modelo_core_mvc
driver.Navigate().GoToUrl(baseURL);
// Encontre o titulo da página
IWebElement pageTitle = driver.FindElement(By.CssSelector("h1"));
// Verifique se a página contém o texto "Modelo Sefaz"
if (pageTitle.Text.Contains("Modelo", StringComparison.OrdinalIgnoreCase))
{
// Execute a verificação de acessibilidade
AxeResult axeResult = new AxeBuilder(driver).Analyze();
// Imprime as violações
foreach (var violation in axeResult.Violations)
{
Console.WriteLine(violation.Description);
}
// Falha se houver violações
Assert.That(axeResult.Violations.Count, Is.EqualTo(0));
}
else
{
// Falha se o texto não for encontrado
Assert.That(driver.PageSource.Contains("Modelo", StringComparison.OrdinalIgnoreCase), Is.True);
}
}
private void Selenium_CheckProjectPage()
{
// Navega até a página do modelo_core_mvc
driver.Navigate().GoToUrl(baseURL);
// Encontre e clique no link "Projetos"
driver.FindElement(By.LinkText("Lista de Projetos")).Click();
// Verifique se a página contém o texto "Projetos do DTI"
if (driver.PageSource.Contains("Projetos do", StringComparison.OrdinalIgnoreCase))
{
// Execute a verificação de acessibilidade
AxeResult axeResult = new AxeBuilder(driver).Analyze();
// Falha se houver violações
axeResult.Violations.Should().BeEmpty();
}
else
{
// Falha se o texto não for encontrado
Assert.That(driver.PageSource.Contains("Projetos do", StringComparison.OrdinalIgnoreCase), Is.True);
}
}
private void TakeScreenshot()
{
// O teste falhou, tire uma captura de tela
if ((TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Failed) ||
(TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Inconclusive))
{
// Define o caminho e o nome do arquivo da captura de tela
string screenshotPath = Directory.GetCurrentDirectory() + "\\" + TestContext.CurrentContext.Test.Name + ".png";
// Salve a captura de tela
((ITakesScreenshot)driver).GetScreenshot().SaveAsFile(screenshotPath);
// Adicione o anexo ao contexto do teste
TestContext.AddTestAttachment(screenshotPath, $@"Captura de Tela - {TestContext.CurrentContext.Test.Name}");
}
}
}
}
Para executar esse projeto, basta abrir o arquivo .sln no Visual Studio 2022 ou executar o comando abaixo:
dotnet test
Para automatizar a execução dos testes é possível configurar um build pipeline no Azure DevOps. Para isso, basta criar um novo pipeline e configurar o arquivo azure-pipelines.yml
com o seguinte conteúdo para o Azure DevOps:
trigger:
- main
pool:
vmImage: ubuntu-latest
variables:
- name: BuildConfiguration
value: Release
- name: BuildPlatform
value: any cpu
- name: system.debug
value: false
- name: Projects
value: '**/*.csproj'
steps:
- task: DotNetCoreCLI@2
displayName: Restore
inputs:
command: restore
projects: '$(Projects)'
- task: DotNetCoreCLI@2
displayName: Build
inputs:
projects: '$(Projects)'
arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)'
- task: DotNetCoreCLI@2
displayName: Test
inputs:
command: test
projects: $(Projects)
arguments: '--configuration $(buildConfiguration) --collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format="cobertura"'
continueOnError: true
- task: PublishCodeCoverageResults@1
displayName: 'Publish code coverage from $(Agent.TempDirectory)/**/coverage.cobertura.xml'
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact'
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)'
condition: succeededOrFailed()
Ou com o seguinte conteúdo para o GitHub Actions:
Lembre-se de criar um arquivo dotnet-test-acessibilidade.yml
e coloca-lo na pasta .github\workflows
.
name: dotnet-test-acessibilidade.
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
- name: Test
run: dotnet test --no-build --verbosity normal
continue-on-error: true