Testing
Arquitectura de Cucumber
Arquitectura de Cucumber
Componentes Principales
// Feature Files -> Step Definitions -> Test Execution
@CucumberContextConfiguration
@SpringBootTest(classes = TestConfig.class)
public class TestConfiguration {
@Before
public void setup() {
// Configuración pre-test
}
}
Hooks y Configuración
public class Hooks {
@Before("@ui")
public void setupBrowser() {
// Configuración específica para tests UI
}
@After
public void teardown(Scenario scenario) {
if (scenario.isFailed()) {
// Capturar screenshot o log adicional
}
}
}
Patrones de Implementación
Page Object Model Integration
public class LoginPageSteps {
private LoginPage loginPage;
@Given("I am on the login page")
public void navigateToLogin() {
loginPage.navigateTo();
}
@When("I login with {string} and {string}")
public void loginWithCredentials(String user, String pass) {
loginPage.enterCredentials(user, pass);
loginPage.submit();
}
}
Test Data Management
@Data
@Builder
public class TestUser {
private String username;
private String password;
private String role;
}
@Configuration
public class TestDataConfig {
@Bean
public TestUser defaultUser() {
return TestUser.builder()
.username("testuser")
.password("testpass")
.role("USER")
.build();
}
}
Integraciones Específicas
Base de Datos
public class DatabaseSteps {
@Autowired
private UserRepository userRepository;
@Given("a user exists in database")
public void createUserInDatabase() {
userRepository.save(new User("test", "password"));
}
@Then("the user should be persisted")
public void verifyUserPersisted() {
assertThat(userRepository.findByUsername("test")).isNotNull();
}
}
API Testing
public class ApiSteps {
private Response response;
@When("I call the {string} endpoint")
public void callEndpoint(String endpoint) {
response = given()
.contentType(ContentType.JSON)
.when()
.get(endpoint);
}
@Then("the response status should be {int}")
public void verifyStatus(int expectedStatus) {
assertThat(response.getStatusCode()).isEqualTo(expectedStatus);
}
}
Configuraciones Avanzadas
Properties y Configuración
# application-test.properties
cucumber.filter.tags=@regression
cucumber.publish.quiet=true
cucumber.plugin=pretty, html:target/cucumber.html
Parallel Execution
@Configuration
public class ParallelConfig {
@Bean
@Scope("cucumber-glue")
public WebDriver webDriver() {
return new ChromeDriver();
}
}
Reporting y Monitoreo
Custom Reports
@AfterAll
public static void generateCustomReport() {
// Lógica personalizada para reportes
CucumberReportGenerator.generate();
}
Integración con herramientas externas
public class MetricsCollector {
@AfterStep
public void collectMetrics(Scenario scenario) {
// Recolectar métricas de performance
TestMetrics.recordStepDuration(scenario.getName());
}
}
Best Practices
Organización de Proyecto
src/test/
├── resources/
│ └── features/
│ ├── login/
│ ├── payment/
│ └── user-management/
├── java/
│ └── steps/
│ ├── common/
│ ├── ui/
│ └── api/
└── configuration/
Mantenibilidad
// Reutilización de steps
public class CommonSteps {
@Given("I am an authenticated user")
public void authenticateUser() {
// Lógica común de autenticación
}
}
Performance y Optimización
Configuración de Timeouts
public class TimeoutConfig {
@Before
public void setTimeouts() {
// Configurar timeouts específicos
Wait.setDefaultTimeout(Duration.ofSeconds(30));
}
}
Database Cleanup
@Transactional
public class DatabaseCleanup {
@After("@requiresCleanup")
public void cleanDatabase() {
// Limpiar datos de test
userRepository.deleteAll();
}
}
Troubleshooting
Debug Configuration
public class DebugSteps {
@Given("debug step")
public void debugStep() {
// Punto de interrupción para debugging
System.out.println("Debug point reached");
}
}
Logging Integration
@Slf4j
public class LoggedSteps {
@When("I perform action")
public void performAction() {
log.info("Performing action");
// Implementación del step
}
}
Seguridad en Tests
Authentication Testing
public class SecuritySteps {
@Given("I am authenticated as {string}")
public void authenticateAsRole(String role) {
SecurityContext.setAuthentication(role);
}
@Then("I should have access to {string}")
public void verifyAccess(String resource) {
assertThat(SecurityUtils.hasAccess(resource)).isTrue();
}
}
API Security Testing
public class ApiSecuritySteps {
private Headers authHeaders;
@Given("I have valid API credentials")
public void setupApiCredentials() {
authHeaders = Headers.of(
"Authorization", "Bearer " + generateToken(),
"Content-Type", "application/json"
);
}
@When("I access secured endpoint {string}")
public void accessSecuredEndpoint(String endpoint) {
response = given()
.headers(authHeaders)
.when()
.get(endpoint);
}
}
Mobile Testing Integration
Appium con Cucumber
public class MobileSteps {
private AppiumDriver driver;
@Given("I open the mobile application")
public void openMobileApp() {
driver = new AndroidDriver(new URL("http://localhost:4723"), capabilities);
}
@When("I tap on {string} element")
public void tapOnElement(String elementId) {
WebElement element = driver.findElement(By.id(elementId));
element.click();
}
}
Mobile-Specific Features
@mobile
Feature: Mobile Login
Scenario: Login with biometric authentication
Given the app is installed
When I attempt biometric login
Then I should access the main screen
And biometric prompt should appear
Microservices Testing
Service Integration
public class MicroserviceSteps {
@WireMockInject
private WireMockServer wireMock;
@Given("the user service is available")
public void setupUserService() {
wireMock.stubFor(get(urlEqualTo("/users/1"))
.willReturn(aResponse()
.withStatus(200)
.withBody("{\"id\":1,\"name\":\"test\"}")));
}
}
Contract Testing
public class ContractSteps {
@Given("a valid service contract")
public void validateContract() {
ConsumerDrivenContract contract =
Contract.fromYaml("contracts/user-service.yml");
assertThat(contract.isValid()).isTrue();
}
}
Performance Testing
Load Testing Integration
public class PerformanceSteps {
@When("I execute {int} concurrent requests")
public void executeConcurrentRequests(int requests) {
List<CompletableFuture<Response>> futures =
IntStream.range(0, requests)
.mapToObj(i -> makeAsyncRequest())
.collect(Collectors.toList());
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
}
}
Response Time Validation
public class ResponseTimeSteps {
@Then("the response time should be less than {long} ms")
public void verifyResponseTime(long maxTime) {
assertThat(ResponseTimeTracker.getLastResponseTime())
.isLessThan(maxTime);
}
}
AI/ML Testing
Model Validation
public class MLModelSteps {
@Given("a trained ML model")
public void loadTrainedModel() {
Model model = ModelLoader.load("model.pkl");
TestContext.setModel(model);
}
@When("I provide input {string}")
public void provideModelInput(String input) {
Prediction prediction = TestContext.getModel().predict(input);
TestContext.setPrediction(prediction);
}
@Then("the prediction confidence should be greater than {double}")
public void verifyConfidence(double minConfidence) {
assertThat(TestContext.getPrediction().getConfidence())
.isGreaterThan(minConfidence);
}
}
Cloud Testing
AWS Integration
public class CloudSteps {
private AmazonS3 s3Client;
@Given("a test file in S3 bucket {string}")
public void setupS3File(String bucket) {
s3Client.putObject(bucket, "test-file.txt", "test content");
}
@Then("the file should be processed")
public void verifyFileProcessing() {
assertThat(s3Client.doesObjectExist("processed-bucket", "test-file.txt"))
.isTrue();
}
}
Kubernetes Testing
public class KubernetesSteps {
private KubernetesClient k8sClient;
@Given("the deployment {string} is running")
public void verifyDeploymentRunning(String deployment) {
assertThat(k8sClient.apps().deployments()
.withName(deployment)
.isReady()).isTrue();
}
}
Accessibility Testing
WCAG Compliance
public class AccessibilitySteps {
@Then("the page should meet WCAG {string} guidelines")
public void verifyAccessibility(String level) {
AccessibilityScanner scanner = new AccessibilityScanner(driver);
List<AccessibilityViolation> violations =
scanner.scan(WCAGLevel.fromString(level));
assertThat(violations).isEmpty();
}
}
Screen Reader Testing
Feature: Screen Reader Compatibility
Scenario: Navigate with keyboard only
Given I am using only keyboard navigation
When I tab through the page elements
Then focus should follow logical order
And all interactive elements should be reachable
Internationalization Testing
Multi-language Support
public class LocalizationSteps {
@Given("the application is set to {string} locale")
public void setLocale(String locale) {
LocaleContext.setLocale(Locale.forLanguageTag(locale));
}
@Then("I should see text {string}")
public void verifyLocalizedText(String expectedText) {
assertThat(page.getTextContent()).contains(expectedText);
}
}
RTL Language Support
public class RTLSteps {
@Given("I am using RTL language {string}")
public void setupRTL(String language) {
PageConfig.setDirection("rtl");
PageConfig.setLanguage(language);
}
@Then("the layout should be right-aligned")
public void verifyRTLayout() {
assertThat(page.getComputedStyle("direction")).isEqualTo("rtl");
}
}
Blockchain Testing
Smart Contract Testing
public class BlockchainSteps {
private Web3j web3j;
@Given("a deployed smart contract")
public void setupSmartContract() {
Credentials credentials = Credentials.create("private-key");
contract = SmartContract.deploy(web3j, credentials, GAS_PRICE, GAS_LIMIT);
}
@When("I execute contract function {string}")
public void executeContractFunction(String function) {
TransactionReceipt receipt = contract.executeFunction(function).send();
TestContext.setTransactionReceipt(receipt);
}
}
IoT Testing
Device Simulation
public class IoTSteps {
private MqttClient mqttClient;
@Given("a connected IoT device {string}")
public void simulateDevice(String deviceId) {
mqttClient.connect();
mqttClient.subscribe("devices/" + deviceId + "/commands");
}
@When("I send command {string} to device")
public void sendDeviceCommand(String command) {
mqttClient.publish("devices/" + deviceId + "/commands", command);
}
}
Quantum Computing Testing
Quantum Algorithm Validation
public class QuantumSteps {
private QuantumSimulator simulator;
@Given("a quantum circuit with {int} qubits")
public void setupQuantumCircuit(int qubits) {
circuit = new QuantumCircuit(qubits);
TestContext.setCircuit(circuit);
}
@When("I apply Hadamard gate to qubit {int}")
public void applyQuantumGate(int qubit) {
circuit.h(qubit);
}
@Then("the superposition should be verified")
public void verifySuperposition() {
QuantumResult result = simulator.execute(circuit);
assertThat(result.getProbability(0)).isCloseTo(0.5, within(0.1));
}
}
¿Te gusta este contenido? Suscríbete vía RSS