The Valoraclick QA Tool is organized into four distinct layers following a clean separation of concerns. Each file has a single, well-defined responsibility, making it straightforward to extend or replace individual components — such as swapping the PDF engine or adding a new export target — without touching the rest of the codebase.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Beliagal/qa-report-automation/llms.txt
Use this file to discover all available pages before exploring further.
Layer Overview
The dependency tree flows strictly downward: the entry point boots the GUI, the GUI owns the data model and delegates work to the service layer, and the service layer relies on pure utility functions from the logic layer.models.py — Data Layer
ReportData is a plain Python object with no UI logic and no external dependencies. It exposes two attributes:
metadata— adictkeyed by field labels (e.g."Tester:","Fecha:","resumen") that maps to the string values entered in the UI.pruebas— alistof step dictionaries, each containinginput,esp(expected),obt(obtained),estado(Pass / Fail), andimg(optional screenshot path).
ReportData is a pure data container it can be passed freely between layers — from the GUI to either service — without coupling any layer to the UI framework.
models.py
logic.py — Business Logic
logic.py contains pure functions with no side effects. They take arguments and return values — nothing more. This makes them trivially testable and reusable in any context.
| Function | Purpose |
|---|---|
validar_fecha(fecha_str) | Returns True if the string matches DD/MM/YYYY and is a real calendar date; False otherwise. |
obtener_color_estado(estado) | Maps "Pass" → (46, 204, 113) (green) and any other value → (231, 76, 60) (red) as an RGB tuple. |
logic.py
services.py — Service Layer
The service layer contains two classes that perform I/O operations. Neither class imports fromgui.py or touches any UI widget — they receive a ReportData instance and an output path, do their work, and return.
PDFService
PDFService.generate_report(data, output_path) uses fpdf2 to render a complete PDF report:
- Writes an INFORMACIÓN GENERAL header block from
data.metadata. - Iterates over
data.pruebasand renders a table row for each step, colouring pass rows green and fail rows red. - Embeds any screenshot image found at
step["img"]directly beneath its row. - Calls
pdf.output(output_path)to write the file to disk.
CSVService
CSVService.export(data) writes a timestamped CSV backup to Google Drive:
- Uses
win32com.clientto resolve a Windows.lnkshortcut atG:\Mi unidad\Informes.lnkto its real target directory. - Falls back to
G:\Mi unidadif the shortcut cannot be resolved. - Writes a UTF-8 BOM CSV containing all metadata fields and all test step rows.
- Returns a
(bool, str)tuple —(True, full_path)on success or(False, error_message)on failure. The GUI logs the result but never raises to the user on a Drive failure.
gui.py — View Layer
TestingApp extends ctk.CTk and is the orchestrator of the entire application. On construction it:
- Instantiates
ReportData,PDFService, andCSVService. - Builds the UI in three sections via
_setup_top_bar(),_setup_metadata_grid(), and_setup_execution_form(). - Calls
_load_session()to restore any previously saved state fromsesion_testing.json.
| Method | Role |
|---|---|
_sync() | Reads all Entry and Textbox widgets and writes their values into report_data.metadata. |
_on_export() | Validates the date, opens a save-file dialog, calls PDFService then CSVService, and shows a result dialog. |
_on_add() | Appends a new step dict to report_data.pruebas, refreshes the log viewer, and saves the session. |
_on_reset() | Asks for confirmation, calls report_data.reset_data(), clears all widgets, and deletes the session file. |
_save_session() / _load_session() | Serialize / deserialize report_data to sesion_testing.json for crash-safe persistence. |
_on_img() | Opens a file picker for PNG/JPG screenshots and stores the chosen path in self.current_img. |
_update_log() | Redraws the live-preview log textbox with colour-coded step entries. |
main.py — Entry Point
main.py is intentionally minimal. It imports TestingApp, instantiates it, and hands control to the Tk event loop. No application logic lives here.
main.py
Data Flow
Understanding how data moves through the layers is the key to extending the tool:_sync() is always called before any export so that the latest widget values are flushed into ReportData before it is handed to either service.
The repository also contains a
testing_gui.py file — an alternative monolithic prototype that combines all layers (data, logic, services, and UI) into a single file. It was an early proof of concept. The production codebase uses the modular structure described on this page: models.py, logic.py, services.py, and gui.py as separate, independently testable modules.