Skip to content

Robottelo Contributing Guidelines

Ondřej Gajdušek edited this page Aug 9, 2024 · 16 revisions

Robottelo Contributing Guidelines and Best Practices

Table of Contents


Introduction

Welcome to the Robottelo project! This document provides essential information for contributing to the project, including best practices for writing and organizing tests, managing helper functions, code structure, and guidelines for pull requests.

The goal is to ensure contributors can efficiently locate existing helpers, add new ones in the right place, and maintain consistency across the project.

General Best Practices

  • API Calls First: Prefer API calls over UI and CLI interactions for test setups unless specific endpoint setups are needed. UI should be the last resort.
  • Target Satellite Fixtures: Use target_sat fixtures in tests to leverage the wide range of helper methods provided by the Satellite object.
  • Non-Reusable Helpers: Place non-reusable helpers close to the test module itself.
  • Avoid One-Liners: If a helper is a one-liner, directly replace the function code where it's used.

Test Case Guidelines

Test Case IDs

  • Retain test case IDs unless the test's logic or purpose significantly changes.
  • Generate a new test ID if the fundamentals of the test change.

Test Structure

  • Robottelo follows the pytest framework.
  • Arrange-Act-Assert: Structure tests by performing setup (Arrange) in fixtures, actions (Act), and assertions (Assert). For CLI and UI modules, use APIs in the Arrange phase and the UI/CLI for the Act phase.

Test Generation Mechanism

  • Understand the test generation mechanism through the supportability configuration. [Link to the documentation].

Test Writing Conventions

Each test needs to start with test_ in its name to be properly collected by pytest. The test must include a docstring containing critical information and several keywords for documentation and tracking. See the Test Case Naming Conventions wiki page for more details.

Required Docstring Content:

  • Short Description: Briefly describe what the test does.
  • :id: Unique identifier for the test (e.g., using uuidgen or python -c 'import uuid; print(uuid.uuid4())').
  • :parametrized: {yes|no} Specify if the test is parametrized (using @pytest.mark.parametrize). This is important for tools like Polarion.
  • :setup: Describe steps needed to prepare the testing environment, often handled by fixtures.
  • :steps: Describe the steps the test performs.
  • :expectedresults: Describe the expected outcomes of the test.

Optional Docstring Keywords:

  • :BlockedBy: SAT-12345 Use to skip the test until a specific Jira issue is resolved.
  • :Verifies: SAT-67890 Use to indicate that the test covers a particular Jira issue.
  • :customerscenario: true Use if the test covers a bug linked to a customer case.

Inherited or Test-Specific Keywords:

  • :CaseAutomation: {Automated|NotAutomated|ManualOnly} Typically set to Automated.
  • :CaseComponent: <component_name> E.g., Repositories, ActivationKeys.
  • :team: <team_name> E.g., Phoenix-subscriptions, Rocket.
  • :CaseImportance: {Critical|High|Medium|Low} Based on the importance or severity of the issue being tested.

Validating Docstrings:

  • To check the validity of docstrings, use the command:
    $ make test-docstrings

Writing and Organizing Code

Helper Functions

  • Isolation and Encapsulation: Create helper functions to isolate shared logic and encapsulate complex operations.
  • Organizing Helpers:
    • Use api_factory.py, cli_factory.py, and ui_factory.py for helpers related to API, CLI, and UI operations, respectively.
    • For helpers that operate across all interfaces (API/CLI/UI), prefer API-based helpers.
    • Place helpers in mixin classes for functionality extending Satellite, Capsule, and Host classes.
    • Add general-purpose helpers that don't operate on hosts to the utils package.

Using Fixtures

  • Fixture Placement: Place fixtures in the pytest_fixtures directory. Core and component-specific fixtures should be organized under appropriate subdirectories.
  • Reusability: Reuse existing fixtures wherever possible. Before adding a new fixture, check for similar or existing ones.
  • Scope and Dependency: Choose fixtures when caching based on scope, dependency on other fixtures, or when setup/teardown is required.

Using Constants

  • Use constants to avoid hardcoding values in tests and helpers.

Packages and Modules

  • pytest_fixtures: Contains globally accessible fixtures for setup and teardown, organized by component and core functionality.

    • broker.py: Contains target_sat fixtures for consistent satellite instances.
    • contenthosts.py: Houses content host creation fixtures.
    • sat_cap_factory.py: Contains satellite/capsule creation fixtures.
    • xdist.py: Manages xDist distribution for Robottelo tests.
  • Robottelo: Contains modules for helper functions:

    • host_helpers/: Houses APIFactory, CLIFactory, UIFactory, and mixin classes.
    • utils/: General utilities that do not operate on hosts directly.
    • hosts.py: Contains the main classes for ContentHost, Capsule, and Satellite.

Finalizers

  • Use finalizers in pytest to clean up after tests. Proper resource cleanup is crucial to avoid side effects in other tests.

Logging Guidelines

  • Extensive Logging: Log as much as possible to aid in debugging and understanding test flow.
  • Log Levels:
    • DEBUG: For detailed diagnostic information.
    • INFO: General progress information.
    • WARNING: Indicators of potential issues.
    • ERROR: Errors that prevent further execution.

Pull Request Guidelines

  • Detailed Descriptions: Always fill in the PR description using the provided template. Include as much context as possible to facilitate the review process.
  • Use the PR Template: Follow the project's PR template to ensure all necessary information is included.

FAQs

When should I prefer/not prefer fixtures over helper functions?

  • Fixtures are preferred when caching based on scope, having dependencies, or requiring setup/teardown.

Where should I implement a global fixture?

  • Use the pytest_fixtures package, choosing core for framework-level or component for component-specific fixtures.

Where should I implement helper functions needed by fixtures?

  • Place reusable functions in utils, or keep them in the fixture's module if they aren't reusable.

Preferred user interface for cross-interface helpers?

  • API helpers are preferred. Use CLI/UI only if necessary.

Where should a property/method describing Satellite/Capsule/Host be added?

  • Add properties/methods to the Satellite, Capsule, or ContentHost classes.

Where should operations on Satellite/Capsule/Host be implemented?

  • Add to the appropriate mixin classes in robottelo/host_helpers/*_mixins.py.

When to prefer host object methods over utils functions?

  • Prefer host object methods when they depend on existing host methods or attributes.

Where should utility helpers that don't fit in existing modules be placed?

  • Add them to robottelo/utils/__init__.py.

Where to place upgrade scenario helpers?

  • Follow the same rules as for other helpers. Place them where they logically fit within the structure.

What to do with duplicate helper methods?

  • Consider merging them with optional parameters if feasible. If distinct CLI/API requirements exist, keep them separate.

By adhering to these guidelines and best practices, you'll contribute to maintaining high code quality and consistency in the Robottelo project. Thank you for your contributions!