Web Application Testing
anthropics/skills
Tests local web applications with Python Playwright scripts, checking frontend behavior, capturing screenshots and reading browser console logs.
Generate TIR (TOTVS Interface Robot) end-to-end test scripts in Python for Protheus SmartClient/Webapp screens.
$ npx skills add totvs/engpro-advpl-tlpp-skills --skill tir-test-generator -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install totvs/engpro-advpl-tlpp-skills tir-test-generator --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/totvs/engpro-advpl-tlpp-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/advpl-tlpp/tir-test-generator .claude/skills/tir-test-generator && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "tir-test-generator" agent skill from https://github.com/totvs/engpro-advpl-tlpp-skills/tree/main/skills/advpl-tlpp/tir-test-generator into .claude/skills/tir-test-generator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tir-test-generator", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/totvs/engpro-advpl-tlpp-skills/tree/main/skills/advpl-tlpp/tir-test-generatorType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add totvs/engpro-advpl-tlpp-skills --skill tir-test-generator -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install totvs/engpro-advpl-tlpp-skills tir-test-generator --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/totvs/engpro-advpl-tlpp-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/advpl-tlpp/tir-test-generator .agents/skills/tir-test-generator && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "tir-test-generator" agent skill from https://github.com/totvs/engpro-advpl-tlpp-skills/tree/main/skills/advpl-tlpp/tir-test-generator into .agents/skills/tir-test-generator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tir-test-generator", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add totvs/engpro-advpl-tlpp-skills --skill tir-test-generator -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install totvs/engpro-advpl-tlpp-skills tir-test-generator --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/totvs/engpro-advpl-tlpp-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/advpl-tlpp/tir-test-generator .cursor/skills/tir-test-generator && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "tir-test-generator" agent skill from https://github.com/totvs/engpro-advpl-tlpp-skills/tree/main/skills/advpl-tlpp/tir-test-generator into .cursor/skills/tir-test-generator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tir-test-generator", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/totvs/engpro-advpl-tlpp-skills.git --path skills/advpl-tlpp/tir-test-generator--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add totvs/engpro-advpl-tlpp-skills --skill tir-test-generator -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install totvs/engpro-advpl-tlpp-skills tir-test-generator --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/totvs/engpro-advpl-tlpp-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/advpl-tlpp/tir-test-generator .gemini/skills/tir-test-generator && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "tir-test-generator" agent skill from https://github.com/totvs/engpro-advpl-tlpp-skills/tree/main/skills/advpl-tlpp/tir-test-generator into .gemini/skills/tir-test-generator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tir-test-generator", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install totvs/engpro-advpl-tlpp-skills tir-test-generatorInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add totvs/engpro-advpl-tlpp-skills --skill tir-test-generator -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/totvs/engpro-advpl-tlpp-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/advpl-tlpp/tir-test-generator .github/skills/tir-test-generator && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "tir-test-generator" agent skill from https://github.com/totvs/engpro-advpl-tlpp-skills/tree/main/skills/advpl-tlpp/tir-test-generator into .github/skills/tir-test-generator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tir-test-generator", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add totvs/engpro-advpl-tlpp-skills --skill tir-test-generator -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install totvs/engpro-advpl-tlpp-skills tir-test-generator --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/totvs/engpro-advpl-tlpp-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/advpl-tlpp/tir-test-generator .opencode/skills/tir-test-generator && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "tir-test-generator" agent skill from https://github.com/totvs/engpro-advpl-tlpp-skills/tree/main/skills/advpl-tlpp/tir-test-generator into .opencode/skills/tir-test-generator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tir-test-generator", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
tir-test-generatorGenerate TIR (TOTVS Interface Robot) end-to-end test scripts in Python for Protheus SmartClient/Webapp screens.
Tir Test Generator is an agent skill from totvs/engpro-advpl-tlpp-skills. Generate TIR (TOTVS Interface Robot) end-to-end test scripts in Python for Protheus SmartClient/Webapp screens. Supports CRUD screen tests, MVC screen tests, grid interaction, report tests, field validation, and message box assertions. Use when a user says "TIR test", "interface test", "e2e test Protheus", "SmartClient test", "Webapp test", "screen test", "create Python test for Protheus screen", or "automate Protheus UI test".
Its SKILL.md is about 4.8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 4 other files, including reference files (for example `references/tir-setup-and-best-practices.md`, `references/tir-test-patterns.md` and `references/tir-webapp-methods-reference.md`).
It sits in Testing & QA, covering End-to-end testing. It works with Python. The repository describes itself as: Repositório contendo skills para orientar desenvolvimento ADVPL/TLPP com agentes de IA. The licence is MIT.
5 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 3908e4e. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are python and json).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Tir Test Generator loads about 4.8k tokens when it runs, and up to ~12k if it reads all its reference files. Until then it costs about 113 tokens; SKILL.md has 1,747 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from totvs/engpro-advpl-tlpp-skills at commit 3908e4e, republished under its MIT licence (© totvs). 1,747 words, ~4,780 tokens.
.claude/skills/tir-test-generator/SKILL.md (or your agent's skills folder). This skill also uses 3 other files; get the full folder from GitHub.Generate end-to-end interface test scripts in Python for the TOTVS Protheus ERP using the TIR (TOTVS Interface Robot) framework. TIR automates Protheus screens through the SmartClient/Webapp interface, validating complete user workflows including screen navigation, field interaction, grid manipulation, button clicks, and result assertions.
TIR tests use Python's unittest framework combined with the tir.Webapp class to:
Program()Use this skill when:
Webapp class| Routine type | TIR class | Import |
|---|---|---|
MVC (ModelDef/ViewDef/MenuDef) | Webapp | from tir import Webapp |
Legacy Browse (MBrowse, AxCadastro) | Webapp | from tir import Webapp |
Every TIR test project requires three files:
| File | Responsibility |
|---|---|
{ROUTINE}TESTCASE.py | Test class with unittest.TestCase, setUpClass, test methods (test_*), tearDownClass |
{ROUTINE}TESTSUITE.py | Runner: imports TESTCASE, builds unittest.TestSuite, executes with TextTestRunner |
config.json | Environment configuration — URL, browser, credentials, Protheus environment name |
Without config.json in the same directory, TIR cannot connect to Protheus.
{test_directory}/
├── {ROUTINE}TESTCASE.py ← test class
├── {ROUTINE}TESTSUITE.py ← runner (CI/CD entry point)
└── config.json ← environment config (REQUIRED){
"Url": "http://{server}:{port}/",
"Browser": "Chrome",
"Environment": "{environment_name}",
"User": "{username}",
"Password": "{password}",
"Language": "pt-br"
}For the complete config.json parameter reference (all sections: Required, Additional, Logging, Database, Chrome), see tir-setup-and-best-practices.md.
from tir import Webapp
import unittest
class {ROUTINE}(unittest.TestCase):
"""
TIR E2E Tests for {ROUTINE} - {Description}
Module: {MODULE}
Tables: {TABLE_ALIASES}
"""
@classmethod
def setUpClass(inst):
"""Setup: Initialize Webapp, configure environment, open routine"""
inst.oHelper = Webapp()
inst.oHelper.Setup('{MODULE}', '{DATE}', 'T1', '{BRANCH}')
inst.oHelper.Program('{ROUTINE}')
def test_{ROUTINE}_CT001(self):
"""CT001 — Include record with required fields"""
self.oHelper.SetButton('Incluir')
self.oHelper.SetBranch('{BRANCH}')
self.oHelper.SetValue('{Field Label 1}', '{value1}')
self.oHelper.SetValue('{Field Label 2}', '{value2}')
self.oHelper.SetButton('Salvar')
self.oHelper.SearchBrowse(f'{BRANCH}{search_key}', key='Filial+{Search Column}')
self.oHelper.SetButton('Visualizar')
self.oHelper.CheckResult('{FIELD_NAME}', '{expected_value}')
self.oHelper.SetButton('Cancelar')
self.oHelper.AssertTrue()
def test_{ROUTINE}_CT002(self):
"""CT002 — Edit existing record"""
self.oHelper.SearchBrowse(f'{BRANCH}{search_key}', key='Filial+{Search Column}')
self.oHelper.SetButton('Alterar')
self.oHelper.SetValue('{Field Label}', '{new_value}')
self.oHelper.SetButton('Salvar')
self.oHelper.AssertTrue()
def test_{ROUTINE}_CT003(self):
"""CT003 — Delete record"""
self.oHelper.SearchBrowse(f'{BRANCH}{search_key}', key='Filial+{Search Column}')
self.oHelper.SetButton('Outras Ações', sub_item='Excluir')
self.oHelper.SetButton('Confirmar')
self.oHelper.AssertTrue()
def test_{ROUTINE}_CT004(self):
"""CT004 — Validate required field rule (negative)"""
self.oHelper.SetButton('Incluir')
self.oHelper.SetButton('Salvar')
self.oHelper.CheckHelp(text_help='{HELP_ID}', button='Fechar')
self.oHelper.SetButton('Cancelar')
self.oHelper.AssertFalse()
@classmethod
def tearDownClass(inst):
"""Teardown: Close session and collect results"""
inst.oHelper.TearDown()
if __name__ == '__main__':
unittest.main()import unittest
from {ROUTINE}TESTCASE import {ROUTINE}
suite = unittest.TestSuite()
suite.addTest({ROUTINE}('test_{ROUTINE}_CT001'))
suite.addTest({ROUTINE}('test_{ROUTINE}_CT002'))
suite.addTest({ROUTINE}('test_{ROUTINE}_CT003'))
suite.addTest({ROUTINE}('test_{ROUTINE}_CT004'))
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)For the complete TIR Webapp API reference (Setup & Lifecycle, Field Interaction, Browse & Navigation, Grid Operations, Assertions & Validation, Dialog Handling, Parameters & Configuration), see tir-webapp-methods-reference.md.
For all complete test script templates (Standard CRUD, Master-Detail with Grid, Tabs/Folders, View/Validate, Validation Error, Other Actions Menu, Report with Parameters, Grid Checkbox Selection), see tir-test-patterns.md.
When generating TIR test scripts, follow this process:
| Screen Type | Characteristics | Key Methods |
|---|---|---|
| Simple CRUD | Single form, no grid | SetValue, SetButton, CheckResult |
| Master-Detail | Form + grid (e.g., invoice header + items) | SetValue (grid=True), LoadGrid, ClickGridCell |
| Tabbed Screen | Multiple folders/tabs | ClickFolder, SetValue per tab |
| Browse + Actions | Browse grid with action menu | SearchBrowse, SetButton('Outras Ações', sub_item=...) |
| Report | Parameter screen + output | SetValue for params, SetButton('OK'), WaitProcessing |
| Wizard | Multi-step dialog flow | SetButton('Avançar'), SetButton('Finalizar') |
For each test, identify:
SetValue)CheckResult, e.g., 'A1_COD', 'B1_DESC')'Incluir', 'Alterar', 'Salvar', 'Cancelar')SearchBrowse — see UI Conventions & Pitfalls below for the right ruleThese are the details that separate a TIR script that runs from a script that fails at the first click. They are not negotiable — they came from running against real Protheus environments.
The key= argument must match the browse column header as rendered on screen, not a generic pattern. Two common headers in MVC routines:
| Routine trait | key value | Search term example |
|---|---|---|
Browse keyed only by {ALIAS}_COD | 'Filial+codigo' | 'D MG 01000033' |
Browse keyed by {ALIAS}_COD + {ALIAS}_LOJA (customers, suppliers) | 'Filial+codigo + Loja' | f'D MG 01{cod+loja}' |
| Modern routines with composite semantic header | Copy the header verbatim | — |
Rule of thumb: the browse header is the source of truth. If in doubt, open the browse in a real session and read the sort-selector label. Do not invent 'Filial+codigo + Loja' for a routine that browses only by code — SearchBrowse will scroll past the record and never find it.
When "Outras Ações" opens a sub-menu that opens another sub-menu (e.g., Outras Ações → Oportunidades → Nova Oportunidade), TIR requires pipe-separated sub-items:
# Correct — nested sub-menu with pipe
self.oHelper.SetButton('Outras Ações', sub_item='Oportunidades|Nova Oportunidade')
# Wrong — loses the intermediate level, click never registers
self.oHelper.SetButton('Outras Ações', sub_item='Nova Oportunidade')If the spec path has → X → Y (two arrows after the main menu), use sub_item='X|Y'.
Cancelar vs Fechar vs SairDifferent screens use different close labels. The convention in Protheus MVC is:
| Screen context | Button to close |
|---|---|
Form opened by Visualizar, Incluir, Alterar | 'Cancelar' |
| Related-action screen (sub-window) that only lists or reads data | 'Fechar' |
| Wizard last step that only confirms | 'Concluir' or 'Finalizar' |
| Main browse session | TearDown() closes it — never click manually |
Never use 'Sair' unless you have verified on the real screen. 'Sair' is rare in modern MVC and most of the time produces a ghost click that TIR reports as success while nothing happened.
CheckResult — technical name vs label| Situation | Use |
|---|---|
The field has a clear {ALIAS}_{NAME} in the dictionary and the screen is the main form (Visualizar/Alterar of the routine being tested) | Technical name ('A1_COD', 'C5_CLIENTE') |
| The field belongs to a related screen called as an action (Nova Oportunidade, Novo Apontamento, Facilitador) — you may not know the alias of that secondary model | Screen label ('Cliente', 'Nome') |
Do not guess technical names for related screens. If the spec only gives a label and the routine alias is different (UA_*, AE_*, etc.), use the label. A wrong technical name fails silently or — worse — matches a different field with the same prefix.
Validating that a related screen opened is best done by asserting content, not just presence:
# Weak — asserts something appeared but doesn't prove it's the right thing
self.oHelper.WaitShow('Subclientes')
# Strong — confirms the expected child record is listed
self.oHelper.SearchBrowse(f'D MG 01{filho+loja}', key='Filial+codigo + Loja')Use WaitShow as a safety net before the content assertion, not as a replacement for it.
The Setup() branch string and the SearchBrowse branch prefix must be character-for-character identical, including trailing spaces. 'D MG 01' (no space) and 'D MG 01 ' (trailing space) are different keys in the browse. Match what the live environment renders.
| Scenario | Pattern | Assertion |
|---|---|---|
| Include with required fields | Fill fields → Salvar → SearchBrowse → Visualizar → CheckResult → Cancelar | AssertTrue() |
| Edit existing record | SearchBrowse → Alterar → SetValue → Salvar | AssertTrue() |
| Delete record | SearchBrowse → Outras Ações/Excluir → Confirmar | AssertTrue() |
| Required field validation | Incluir → Salvar (empty) → CheckHelp → Cancelar | AssertFalse() |
| Business rule validation | Fill invalid values → Salvar → CheckHelp → Cancelar | AssertFalse() |
| Interaction | Method |
|---|---|
| Open routine | Program('{ROUTINE}') |
| Set branch after Incluir | SetBranch('{BRANCH}') |
| Click a button | SetButton('{Label}') |
| Click sub-menu button | SetButton('{Main}', sub_item='{Sub}') |
| Fill a form field | SetValue('{Label}', '{value}') |
| Fill a grid cell | SetValue('{Column}', '{value}', grid=True, grid_number=1, row=N) |
| Refresh grid | LoadGrid() |
| Switch tab | ClickFolder('{Tab Name}') |
| Search in browse | SearchBrowse(f'{BRANCH}{key}', 'Filial+{Column}') |
| Check field value | CheckResult('{FIELD_NAME}', '{expected}') |
| Handle error dialog | CheckHelp(text_help='{ID}', button='Fechar') |
| Wait for processing | WaitProcessing('{message}') |
| Send keyboard key | SetKey('{KEY}', grid=True/False) |
After generating the TESTCASE, always generate the TESTSUITE that:
unittest.TestSuite()suite.addTest()unittest.TextTestRunner(verbosity=2)The moments the generator is most tempted to cut corners — and what actually happens.
| Temptation | Reality |
|---|---|
"I don't know the alias of the secondary screen, but UA_CLIENTE looks right for an opportunity, let me guess." | Wrong alias = silent failure or wrong field matched. Use the screen label ('Cliente') when the secondary screen's model is not in your context. Guessing propagates to every future test of that routine. |
"The spec says Outras Ações → Oportunidades → Nova Oportunidade, but I'll just pass 'Nova Oportunidade' — TIR will find it." | No. Sub-menu navigation is literal. Drop the middle level and the click never happens. Use pipes: sub_item='Oportunidades|Nova Oportunidade'. |
"The browse header might be 'Filial+codigo + Loja' — that's the MATA030 pattern, CRMA980 must be the same." | Not guaranteed. Different browses, different headers. Look at the real screen or the MenuDef before committing to key=. |
"'Sair', 'Fechar', 'Cancelar' — whatever, they all close the window." | They close different windows. A wrong label produces a TIR warning that most CI pipelines swallow. See Close buttons above. |
"WaitShow('SubClientes') is enough — if the screen appeared, the test passes." | No. WaitShow only confirms a string is on the page. Assert content (the expected child record, a specific field value). |
"The spec references pre-existing customers 000033, 000050... I'll just use them. If they don't exist, TIR will create an error and we catch it later." | The error is SearchBrowse did not find. The test marks as failure, not as missing-data. Ensure the required records exist in the environment before running the suite — add a setUpClass step that creates them via ExecAuto, or document them as a manual prerequisite in the test file header. |
"I'll leave {server} or {port} in config.json — the user will fix it." | config.json without real values fails at connection, the test never starts, the user debugs the wrong layer. Either fill with sensible defaults (localhost, 8080) or explicitly mark the file with a TODO comment. |
For environment setup (Python, Webapp, tir.json configuration) and best practices (test independence, naming conventions, screen interactions, assertions, environment isolation), see tir-setup-and-best-practices.md.
Before finalizing generated TIR test scripts, verify:
config.json:
Url, Browser, Environment, User, Password, Language all set{server}, {username} remainingTESTCASE file ({ROUTINE}TESTCASE.py):
{ROUTINE}TESTCASE.py{ROUTINE} inheriting from unittest.TestCasefrom tir import WebappsetUpClass(inst) contains the correct class instantiation, Setup(), and Program() callstearDownClass(inst) contains TearDown() callSetup() has correct module, date, group, and branch (4 args — 5th module is optional)test_ prefix and has a docstringself.oHelper.AssertTrue() — NO parametersself.oHelper.AssertFalse() — NO parametersWebapp-specific (MVC/Legacy):
SetBranch() called after SetButton('Incluir') when neededSearchBrowse(term, key=...) uses key= kwarg with branch-prefixed termkey= value matches the real browse header — single-key routines use 'Filial+codigo', composite-key routines use 'Filial+codigo + Loja' (verify, don't assume)Setup() matches exactly the branch padding in SearchBrowse (trailing space matters)sub_item='Level1\|Level2''Cancelar' for Visualizar/Alterar/Incluir forms; 'Fechar' for related-action sub-windows; 'Concluir'/'Finalizar' for wizard endings; never 'Sair' without verifying on the real screenCheckResult uses technical names ('A1_COD') only for the routine's own form; uses screen labels ('Cliente', 'Nome') for secondary screens whose model alias is unknown — do NOT guess aliasesSearchBrowse, specific field via CheckResult) — WaitShow alone is not enoughCheckHelp(text_help=..., button=...) for error dialogsLoadGrid() called after grid SetValue operationsTESTSUITE file ({ROUTINE}TESTSUITE.py):
{ROUTINE}TESTSUITE.pyimport unittest presentfrom {ROUTINE}TESTCASE import {ROUTINE} presentsuite = unittest.TestSuite() createdsuite.addTest({ROUTINE}('test_{ROUTINE}_CT00N')) for each test methodrunner = unittest.TextTestRunner(verbosity=2) presentrunner.run(suite) presentBoth files:
{ROUTINE}, {VALUE}, {FIELD} remainingAssertTrue(value, msg) with parameters — TIR does not accept parameters| Skill | When to Use Instead |
|---|---|
mvc-generator | Creating MVC routines (the screens being tested) |
tlpp-rest-endpoint-generator | Creating REST endpoints |
© totvs, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 3 other files (references) in skills/advpl-tlpp/tir-test-generator of totvs/engpro-advpl-tlpp-skills.
Open the folder on GitHubat commit 3908e4e
Tir Test Generator next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Tir Test Generator this skilltotvs/engpro-advpl-tlpp-skills | 143 | — | ~4.8k | Automated safety check: Pass | MIT | |
| Web Application Testinganthropics/skills | 180k | 51 repos | ~966 | Automated safety check: Pass | Apache-2.0 | |
| OpenHarness End-to-End EvalsHKUDS/OpenHarness | 16k | 1 repos | ~2.1k | Automated safety check: Notes | MIT | |
| JSON Repair Docs Demo Local Testmangiucugna/json_repair | 5.1k | — | ~549 | Automated safety check: Pass | MIT | |
| RStudio Selenium to Playwright Migrationrstudio/rstudio | 5.1k | — | ~3.6k | Automated safety check: Pass | Custom licence | |
| Godot E2ERandallLiuXin/GodotMaker | 550 | 1 repos | ~3.9k | Automated safety check: Pass | Custom licence |
anthropics/skills
Tests local web applications with Python Playwright scripts, checking frontend behavior, capturing screenshots and reading browser console logs.
HKUDS/OpenHarness
Validates OpenHarness features by running real multi-turn agent loops with live LLM calls against an unfamiliar codebase, checking actual tool execution.
mangiucugna/json_repair
Runs the json_repair docs demo against a local Flask API and static server, so changes to docs/app.py or the docs UI are checked end to end before publishing.
rstudio/rstudio
Converts RStudio Python Selenium electron tests into TypeScript Playwright tests, checking each against a live RStudio before counting it as migrated.
RandallLiuXin/GodotMaker
Write and run E2E (end-to-end) game tests using the godot-e2e framework.
liaohch3/claude-tap
Runs a real Codex CLI session through claude-tap and produces trace evidence and viewer screenshots for pull requests that touch capture, proxying or the viewer.
totvs/engpro-advpl-tlpp-skills
Converts AdvPL and TLPP source files from UTF-8 to Windows-1252 in place after code generation, because the Protheus compiler accepts only CP1252 files.
totvs/engpro-advpl-tlpp-skills
Compiles AdvPL and TLPP sources from VS Code with the TOTVS Developer Studio extension, handling server setup, connection and compile result reporting.
totvs/engpro-advpl-tlpp-skills
Plans and builds Protheus AdvPL/TLPP features through Specify, Design, Tasks and Execute phases whose depth scales with the size of the change.
totvs/engpro-advpl-tlpp-skills
Reviews AdvPL and TLPP source against SonarQube rules, ProtheusDOC requirements, security, performance and Protheus conventions, and reports findings by severity.
totvs/engpro-advpl-tlpp-skills
Queries the TOTVS Protheus ERP data dictionary for tables, fields, indexes, parameters, triggers and lookups, including impact checks during refactoring.
totvs/engpro-advpl-tlpp-skills
Generates Protheus MVC screens in ADVPL/TLPP, with ModelDef, ViewDef, MenuDef and Browse functions for single-entity and master-detail layouts.
Works with
Categories
Generate TIR (TOTVS Interface Robot) end-to-end test scripts in Python for Protheus SmartClient/Webapp screens. Tir Test Generator is an agent skill from totvs/engpro-advpl-tlpp-skills. Generate TIR (TOTVS Interface Robot) end-to-end test scripts in Python for Protheus SmartClient/Webapp screens.
Tir Test Generator fits situations like: A user says TIR test; E2e test Protheus; smartClient test; create Python test for Protheus screen.
Run `npx skills add totvs/engpro-advpl-tlpp-skills --skill tir-test-generator -a claude-code`. Or copy the skill folder (skills/advpl-tlpp/tir-test-generator in totvs/engpro-advpl-tlpp-skills) into .claude/skills/tir-test-generator in your project. Claude Code loads it when a task matches its description.
Run `npx skills add totvs/engpro-advpl-tlpp-skills --skill tir-test-generator -a codex`. Or copy the skill folder (skills/advpl-tlpp/tir-test-generator in totvs/engpro-advpl-tlpp-skills) into .agents/skills/tir-test-generator in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add totvs/engpro-advpl-tlpp-skills --skill tir-test-generator -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/tir-test-generator, .gemini/skills/tir-test-generator, .github/skills/tir-test-generator and .opencode/skills/tir-test-generator in your project.
SKILL.md names no scripts, command-line tools or credentials: Tir Test Generator is instructions for the agent only. Our summary lists: Python 3.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Tir Test Generator is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.8k tokens (SKILL.md is roughly 19k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 7.1k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Tir Test Generator: Web Application Testing (anthropics/skills, 180k stars), OpenHarness End-to-End Evals (HKUDS/OpenHarness, 16k stars), JSON Repair Docs Demo Local Test (mangiucugna/json_repair, 5.1k stars) and RStudio Selenium to Playwright Migration (rstudio/rstudio, 5.1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
totvs (a GitHub organization) maintains it in totvs/engpro-advpl-tlpp-skills, which has 143 GitHub stars. The repository holds 19 skills in this directory. The repository was last updated on October 5, 2026.
Source: totvs/engpro-advpl-tlpp-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.