diff --git a/GLOSSARY_LINKING_GUIDE.md b/GLOSSARY_LINKING_GUIDE.md new file mode 100644 index 0000000..dbb3973 --- /dev/null +++ b/GLOSSARY_LINKING_GUIDE.md @@ -0,0 +1,515 @@ +# Glossary Link Automation Guide + +## Overview + +This guide explains how to automatically add glossary links throughout the Robot Framework RFCP Syllabus documentation. The automation tool identifies glossary terms in documentation files and creates hyperlinks to the interactive glossary page. + +## What This Tool Does + +The glossary linker automatically transforms terms into clickable links: + +**Before:** +```markdown +The Variable Number of Positional Arguments is marked with a single asterisk. +``` + +**After:** +```markdown +The [Variable Number of Positional Arguments](../glossary#variable-number-of-positional-arguments) is marked with a single asterisk. +``` + +The tool: +- ✅ Links 80+ glossary terms automatically +- ✅ Uses relative paths (works in both local dev and production) +- ✅ Preserves code blocks and headings +- ✅ Only links terms in body content (keeps navigation clean) +- ✅ Handles term aliases (e.g., "kwargs" → "Free Named Argument") + +## Prerequisites + +- Python 3.7 or higher +- Git +- Node.js and npm (for testing) +- Write access to the repository + +## Installation + +### 1. Locate the Tool + +The glossary linker tool is located in the repository at: +``` +tools/glossary_linker.py +``` + +If you're setting this up for the first time, the tool should already be in the repository. If not, contact the repository maintainers. + +### 2. Verify Python Installation + +```bash +python3 --version +``` + +You should see Python 3.7 or higher. + +## Usage Instructions + +### Step 1: Navigate to Repository Root + +```bash +cd /path/to/robotframework-RFCP-syllabus +``` + +### Step 2: Create a Feature Branch + +Always work in a feature branch: + +```bash +git checkout -b feature/update-glossary-links +``` + +### Step 3: Run in Test Mode (DRY RUN) + +**IMPORTANT: Always run in dry-run mode first!** + +```bash +python3 tools/glossary_linker.py website/docs --dry-run +``` + +This shows you what would be changed without modifying any files. + +**Review the output:** +- Check the number of files that will be modified +- Verify which terms will be linked +- Ensure no unexpected changes + +Example output: +``` +Processing: website/docs +Dry run: True +Relative paths: True + +============================================================ +SUMMARY +============================================================ +Total files: 45 +Modified: 28 +Terms linked: 234 + +============================================================ +DETAILS +============================================================ + +chapter-02/keyword_interface.md + Terms: 15 + - Variable Number of Positional Arguments: 5x + - Named-Only Argument: 3x + - Free Named Argument: 2x +``` + +### Step 4: Apply Changes + +Once you're satisfied with the dry-run output: + +```bash +python3 tools/glossary_linker.py website/docs +``` + +This will: +- Modify markdown files in `website/docs/` +- Add glossary links to terms in body content +- Preserve headings, code blocks, and frontmatter +- Create a statistics file: `stats.json` + +### Step 5: Review Changes + +Use git to review what was changed: + +```bash +# See all changed files +git status + +# View specific changes +git diff website/docs/chapter-02/keyword_interface.md + +# View summary of changes +git diff --stat website/docs/ +``` + +**What to check:** +- ✅ Links use relative paths: `../glossary#term` +- ✅ Headings are NOT linked: `## 2.5 Keyword Interface` (clean) +- ✅ Body content IS linked: `The [Keyword Interface](../glossary#...)...` +- ✅ Code blocks are unchanged + +### Step 6: Test Locally + +Build and run the documentation locally: + +```bash +cd website +npm install # First time only +npm start +``` + +This opens the documentation at `http://localhost:3000` + +**Test the links:** +1. Navigate to Chapter 2, Section 2.5 +2. Click on a glossary term (e.g., "Variable Number of Positional Arguments") +3. Verify you're taken to the glossary page +4. Verify the correct term is highlighted +5. Test 3-5 different links across different chapters + +**Check navigation:** +1. Look at the left sidebar - terms should NOT be linked +2. Look at Previous/Next buttons - terms should NOT be linked +3. Both should show clean text without `[...]` brackets + +### Step 7: Build for Production + +Test the production build: + +```bash +npm run build +npm run serve +``` + +Navigate to `http://localhost:3000` and verify links work in the production build. + +### Step 8: Commit Changes + +```bash +cd .. # Back to repository root + +# Stage all changes +git add website/docs/ + +# Commit with descriptive message +git commit -m "Add glossary links to documentation + +- Automatically linked 80+ glossary terms +- Links use relative paths for local dev compatibility +- Covers argument types, variables, control structures, core concepts +- Tested locally and in production build +- All links verified working correctly" +``` + +### Step 9: Push and Create Pull Request + +```bash +# Push your branch +git push origin feature/update-glossary-links +``` + +Then create a pull request on GitHub with the following information: + +**PR Title:** Add glossary links to documentation + +**PR Description:** +```markdown +## Summary +Automatically added glossary links throughout the documentation using the glossary linker tool. + +## Changes +- Linked 80+ glossary terms across ~28 files +- Terms include: argument types, variables, control structures, core RF concepts +- Links use relative paths (works in both local dev and production) + +## Testing +- [x] Ran in dry-run mode and reviewed output +- [x] Tested locally with `npm start` +- [x] Verified glossary links work correctly +- [x] Checked sidebar and navigation are clean (no links) +- [x] Tested production build with `npm run build` +- [x] Reviewed git diff for all changed files + +## Statistics +- Total files processed: [X] +- Files modified: [X] +- Terms linked: [X] occurrences + +## Screenshots +[Optional: Add screenshots showing working links] +``` + +## Understanding the Tool + +### How It Works + +The tool processes markdown files in several steps: + +1. **Extracts frontmatter** - YAML metadata at the top of files +2. **Identifies sections** - Separates headings, code blocks, and content +3. **Applies patterns** - Matches glossary terms in content only +4. **Creates links** - Generates relative links to glossary +5. **Preserves structure** - Keeps headings and code blocks unchanged + +### What Gets Linked + +The tool links these types of terms: + +**Argument Types:** +- Mandatory Argument, Optional Argument +- Positional Argument, Named Argument +- Embedded Argument +- Positional or Named Argument +- Variable Number of Positional Arguments (*args, *varargs) +- Named-Only Argument +- Free Named Argument (kwargs, **kwargs) + +**Variables:** +- Variable, Scalar Variable, List Variable +- Variable Scope +- Global Variable, Suite Variable, Local Variable +- Built-In Variables + +**Control Structures:** +- Control Structure +- FOR Loop, WHILE Loop + +**Core Concepts:** +- Keyword, User Keyword, Keyword Library +- Suite, Test Case, Task +- Resource File +- Keyword Interface, Argument Interface + +And 50+ more terms... + +### What Gets Excluded + +The tool does NOT link terms in: + +- ❌ Markdown headings (`#`, `##`, `###`, etc.) +- ❌ YAML frontmatter (`---...---`) +- ❌ Code blocks (` ``` ` or `` ` ``) +- ❌ Existing links +- ❌ HTML `` tags + +This ensures: +- Sidebar navigation stays clean +- Previous/Next navigation stays clean +- Code examples remain unchanged + +### Link Format + +Links are generated as relative paths: + +| File Location | Generated Link | +|--------------|----------------| +| `docs/overview.md` | `./glossary#term` | +| `docs/chapter-02/page.md` | `../glossary#term` | +| `docs/chapter-02/sub/page.md` | `../../glossary#term` | + +This ensures links work in: +- ✅ Local development (`npm start`) +- ✅ Production builds +- ✅ Deployed sites + +## Troubleshooting + +### Issue: Terms Not Being Linked + +**Possible causes:** +1. Term is in a heading +2. Term is in a code block +3. Term is already linked +4. Term is not in the glossary term list + +**Solution:** +- Verify the term exists in `GLOSSARY_DATA` in the script +- Check that it's in body content, not a heading +- Ensure it's not in a `` ``` `` code block + +### Issue: Links Show in Sidebar + +**Symptom:** Sidebar shows `[Keyword Interface](...)` instead of clean text + +**Cause:** Terms were linked in headings + +**Solution:** This shouldn't happen with the current tool. If it does: +1. Revert changes: `git checkout website/docs/` +2. Ensure you're using the latest version of the tool +3. Re-run the tool + +### Issue: Links Don't Work Locally + +**Symptom:** Clicking links shows "Page Not Found" + +**Cause:** Using absolute paths instead of relative paths + +**Solution:** The current tool uses relative paths by default. Verify links in the markdown look like: +- ✅ `../glossary#term` (relative - correct) +- ❌ `/robotframework-RFCP-syllabus/docs/glossary#term` (absolute - incorrect) + +### Issue: Code Examples Have Links + +**Symptom:** Links appear inside code blocks + +**Cause:** Code block not properly detected + +**Solution:** +1. Ensure code blocks use proper markdown (` ``` `) +2. Check for unclosed code blocks +3. Report the issue if it persists + +## Updating the Tool + +### When to Update + +Update the glossary linker when: +- New glossary terms are added +- Term definitions change +- Aliases need to be updated + +### How to Update + +Edit `tools/glossary_linker.py` and modify the `GLOSSARY_DATA` list: + +```python +GLOSSARY_DATA = [ + { + 'term': 'New Term Name', + 'definition': 'Brief definition', + 'abbreviation': 'NTN', # Optional + 'aliases': ['Alternative Name', 'Another Alias'] # Optional + }, + # ... existing terms ... +] +``` + +Then commit the updated tool: + +```bash +git add tools/glossary_linker.py +git commit -m "Update glossary linker with new terms" +``` + +### Testing Updates + +After updating the tool: + +1. Run on a single file first: + ```bash + python3 tools/glossary_linker.py website/docs/chapter-02 --dry-run + ``` + +2. Verify the new terms are detected + +3. Apply to full documentation: + ```bash + python3 tools/glossary_linker.py website/docs + ``` + +## Maintenance + +### Regular Updates + +Run the glossary linker periodically: +- After adding new documentation chapters +- After updating existing content +- Quarterly maintenance runs + +### Re-running the Tool + +The tool is **idempotent** - running it multiple times on the same content will: +- ✅ Not create duplicate links +- ✅ Not modify existing links +- ✅ Only add new links where needed + +You can safely re-run it: + +```bash +python3 tools/glossary_linker.py website/docs +``` + +### Version Control + +The tool itself should be version controlled: +- Keep `tools/glossary_linker.py` in the repository +- Document any updates in commit messages +- Tag releases if making significant changes + +## Best Practices + +### Do's ✅ + +- Always run in `--dry-run` mode first +- Review changes before committing +- Test locally with `npm start` +- Test production build +- Update term list when adding new glossary entries +- Document any issues or improvements + +### Don'ts ❌ + +- Don't skip the dry-run step +- Don't commit without testing +- Don't manually add glossary links (use the tool) +- Don't modify the tool without testing +- Don't run on uncommitted changes without backup + +## Command Reference + +```bash +# Dry run (preview changes) +python3 tools/glossary_linker.py website/docs --dry-run + +# Apply changes +python3 tools/glossary_linker.py website/docs + +# Save statistics +python3 tools/glossary_linker.py website/docs --output stats.json + +# Help +python3 tools/glossary_linker.py --help +``` + +## Getting Help + +If you encounter issues: + +1. Check this guide's troubleshooting section +2. Review the tool's inline documentation +3. Check recent commits for similar issues +4. Open an issue in the repository with: + - What you tried to do + - What happened + - Error messages or unexpected output + - Your Python version + +## Contributing + +### Reporting Issues + +If you find a problem: + +1. Document the issue with examples +2. Include the command you ran +3. Provide sample markdown that shows the problem +4. Open an issue with this information + +### Suggesting Improvements + +Improvements welcome: +- Better term detection +- Additional glossary terms +- Performance optimizations +- Better error messages + +Submit improvements via pull request. + +## License + +This tool is part of the Robot Framework RFCP Syllabus project and follows the same license. + +## Credits + +Maintained by the Robot Framework Foundation and contributors. + +--- + +**Last Updated:** February 2026 + +**Tool Version:** 3.0 (Final) + +**Compatible With:** Robot Framework RFCP Syllabus v2024+ diff --git a/tools/add_glossary_links.sh b/tools/add_glossary_links.sh new file mode 100644 index 0000000..55cd46e --- /dev/null +++ b/tools/add_glossary_links.sh @@ -0,0 +1,201 @@ +#!/bin/bash +# +# RFCP Syllabus - Add Glossary Links +# One-command automation for the robotframework-RFCP-syllabus repository +# + +set -e + +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +RED='\033[0;31m' +NC='\033[0m' + +echo -e "${BLUE}╔════════════════════════════════════════════════════════════╗${NC}" +echo -e "${BLUE}║ Robot Framework RFCP Syllabus - Glossary Link Automation ║${NC}" +echo -e "${BLUE}╚════════════════════════════════════════════════════════════╝${NC}" +echo "" + +# Check if we're in the repository +if [ ! -d "website/docs" ]; then + echo -e "${RED}Error: website/docs directory not found${NC}" + echo "Please run this script from the robotframework-RFCP-syllabus repository root" + echo "" + echo "Expected structure:" + echo " robotframework-RFCP-syllabus/" + echo " └── website/" + echo " └── docs/" + exit 1 +fi + +# Check if glossary_linker.py exists +if [ ! -f "glossary_linker.py" ]; then + echo -e "${RED}Error: glossary_linker.py not found${NC}" + echo "Please ensure glossary_linker.py is in the repository root" + exit 1 +fi + +# Check for Python +if ! command -v python3 &> /dev/null; then + echo -e "${RED}Error: Python 3 is not installed${NC}" + exit 1 +fi + +echo -e "${GREEN}✓${NC} Repository structure verified" +echo -e "${GREEN}✓${NC} Python 3 found: $(python3 --version)" +echo "" + +# Interactive menu +echo "What would you like to do?" +echo "" +echo " 1) Test mode - Preview changes without modifying files (RECOMMENDED FIRST)" +echo " 2) Apply changes - Add glossary links to all documentation" +echo " 3) Process Chapter 2 only - Test on the chapter with most terms" +echo " 4) Process specific chapter - Choose which chapter to process" +echo " 5) Show statistics from last run" +echo " 6) Exit" +echo "" +read -p "Enter your choice (1-6): " choice + +case $choice in + 1) + echo "" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" + echo -e "${BLUE} TEST MODE - No files will be modified${NC}" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" + echo "" + python3 glossary_linker.py website/docs --dry-run + echo "" + echo -e "${GREEN}✓${NC} Test completed" + echo "" + echo "Review the output above to see what would be changed." + echo "If everything looks good, run this script again and choose option 2." + ;; + + 2) + echo "" + echo -e "${YELLOW}WARNING: This will modify files in website/docs/${NC}" + echo "" + read -p "Have you run test mode first? (y/N): " test_done + if [[ ! $test_done =~ ^[Yy]$ ]]; then + echo -e "${RED}Please run test mode first (option 1)${NC}" + exit 1 + fi + + echo "" + read -p "Are you sure you want to continue? (y/N): " confirm + if [[ ! $confirm =~ ^[Yy]$ ]]; then + echo "Cancelled" + exit 0 + fi + + # Create backup + backup_dir="website_docs_backup_$(date +%Y%m%d_%H%M%S)" + echo "" + echo "Creating backup: $backup_dir" + cp -r website/docs "$backup_dir" + + echo "" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" + echo -e "${BLUE} APPLYING CHANGES${NC}" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" + echo "" + + python3 glossary_linker.py website/docs --output rfcp_glossary_stats.json + + echo "" + echo -e "${GREEN}✓${NC} Changes applied successfully!" + echo -e "${GREEN}✓${NC} Backup created: $backup_dir" + echo -e "${GREEN}✓${NC} Statistics saved: rfcp_glossary_stats.json" + echo "" + echo "Next steps:" + echo " 1. Review changes: git diff website/docs/" + echo " 2. Test locally: cd website && npm start" + echo " 3. Commit: git add website/docs/ && git commit -m 'Add glossary links'" + ;; + + 3) + echo "" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" + echo -e "${BLUE} PROCESSING CHAPTER 2${NC}" + echo -e "${BLUE}═══════════════════════════════════════════════════════════${NC}" + echo "" + echo "Chapter 2 contains the most glossary terms (Keyword Interface, Arguments, etc.)" + echo "" + + echo "Step 1: Test mode" + echo "─────────────────" + python3 glossary_linker.py website/docs/chapter-02 --dry-run + + echo "" + read -p "Apply changes to Chapter 2? (y/N): " apply + if [[ $apply =~ ^[Yy]$ ]]; then + echo "" + echo "Step 2: Applying changes" + echo "────────────────────────" + python3 glossary_linker.py website/docs/chapter-02 + echo "" + echo -e "${GREEN}✓${NC} Chapter 2 updated" + echo "Review: git diff website/docs/chapter-02/" + else + echo "No changes made" + fi + ;; + + 4) + echo "" + echo "Available chapters:" + ls -d website/docs/chapter-* 2>/dev/null | sed 's/.*chapter-/ chapter-/' || echo " (no chapters found)" + echo "" + read -p "Enter chapter number (e.g., 02): " chapter_num + + chapter_path="website/docs/chapter-$chapter_num" + if [ ! -d "$chapter_path" ]; then + echo -e "${RED}Error: Chapter not found: $chapter_path${NC}" + exit 1 + fi + + echo "" + echo -e "${BLUE}Processing Chapter $chapter_num${NC}" + echo "" + + echo "Step 1: Test mode" + python3 glossary_linker.py "$chapter_path" --dry-run + + echo "" + read -p "Apply changes? (y/N): " apply + if [[ $apply =~ ^[Yy]$ ]]; then + python3 glossary_linker.py "$chapter_path" + echo "" + echo -e "${GREEN}✓${NC} Chapter $chapter_num updated" + fi + ;; + + 5) + if [ -f "rfcp_glossary_stats.json" ]; then + echo "" + echo -e "${BLUE}Statistics from last run:${NC}" + echo "" + python3 -c "import json; data=json.load(open('rfcp_glossary_stats.json')); print(f\"Total files: {data['total_files']}\"); print(f\"Modified: {data['modified_files']}\"); print(f\"Terms linked: {data['total_terms_linked']}\")" + echo "" + echo "Full details in: rfcp_glossary_stats.json" + else + echo "" + echo -e "${YELLOW}No statistics file found${NC}" + echo "Run option 2 to generate statistics" + fi + ;; + + 6) + echo "Goodbye!" + exit 0 + ;; + + *) + echo -e "${RED}Invalid choice${NC}" + exit 1 + ;; +esac + +echo "" diff --git a/tools/extract_glossary_terms.py b/tools/extract_glossary_terms.py new file mode 100644 index 0000000..9894eab --- /dev/null +++ b/tools/extract_glossary_terms.py @@ -0,0 +1,416 @@ +#!/usr/bin/env python3 +""" +Glossary Term Extractor for Robot Framework RFCP Syllabus + +This script extracts glossary terms from the interactive glossary page +and outputs them in a format that can be used by the glossary linker. +""" + +import json +import re +from typing import List, Dict +from pathlib import Path + + +def extract_from_markdown(glossary_file_path: str) -> List[Dict]: + """ + Extract glossary terms from a markdown glossary file. + + This assumes the glossary is structured with headings for each term. + Adjust the parsing logic based on your actual glossary format. + + Args: + glossary_file_path: Path to the glossary markdown file + + Returns: + List of dictionaries containing term information + """ + terms = [] + + with open(glossary_file_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Example parsing logic - adjust based on your glossary structure + # This is a simplified example assuming each term is a heading + + # Pattern to match glossary entries + # Adjust this regex based on your actual glossary format + pattern = r'###\s+(.+?)\n\n(.+?)(?=\n###|\Z)' + + matches = re.finditer(pattern, content, re.DOTALL) + + for match in matches: + term = match.group(1).strip() + definition = match.group(2).strip() + + # Extract abbreviation if present (example: "Term (ABBR)") + abbr_match = re.search(r'\(([A-Z]{2,})\)', term) + abbreviation = abbr_match.group(1) if abbr_match else '' + + # Clean the term name + term_clean = re.sub(r'\s*\([A-Z]{2,}\)', '', term).strip() + + # Extract aliases from "See also: ..." or "Also known as: ..." + aliases = [] + alias_match = re.search(r'(?:See also|Also known as|Alias(?:es)?)[:\s]+(.+?)(?:\n|$)', definition) + if alias_match: + alias_text = alias_match.group(1) + aliases = [a.strip() for a in re.split(r',|;|\band\b', alias_text)] + + terms.append({ + 'term': term_clean, + 'definition': definition, + 'abbreviation': abbreviation, + 'aliases': aliases + }) + + return terms + + +def extract_from_html_table(html_content: str) -> List[Dict]: + """ + Extract glossary terms from HTML table format. + + This is useful if you're scraping from a rendered HTML page. + + Args: + html_content: HTML content containing the glossary table + + Returns: + List of dictionaries containing term information + """ + from html.parser import HTMLParser + + class GlossaryTableParser(HTMLParser): + def __init__(self): + super().__init__() + self.terms = [] + self.current_term = None + self.current_definition = None + self.in_term_cell = False + self.in_def_cell = False + self.cell_data = [] + + def handle_starttag(self, tag, attrs): + if tag == 'td': + # Determine which column we're in + self.cell_data = [] + + def handle_endtag(self, tag): + if tag == 'td': + if self.current_term is None: + # This is the term cell + self.current_term = ''.join(self.cell_data).strip() + else: + # This is the definition cell + self.current_definition = ''.join(self.cell_data).strip() + + # Process the term + if self.current_term and self.current_definition: + # Check if it's a "See ..." reference + see_match = re.match(r'See\s+(.+)', self.current_definition) + + if see_match: + # This is an alias + # We'll handle this in post-processing + pass + else: + # Extract abbreviation from definition + abbr = '' + abbr_match = re.search(r'\b([A-Z]{2,})\b', self.current_definition) + if abbr_match: + abbr = abbr_match.group(1) + + self.terms.append({ + 'term': self.current_term, + 'definition': self.current_definition, + 'abbreviation': abbr, + 'aliases': [] + }) + + # Reset for next row + self.current_term = None + self.current_definition = None + + def handle_data(self, data): + self.cell_data.append(data) + + parser = GlossaryTableParser() + parser.feed(html_content) + return parser.terms + + +def extract_from_structured_data(data_file: str) -> List[Dict]: + """ + Extract glossary terms from a structured data file (JSON, YAML, etc.). + + Args: + data_file: Path to the data file + + Returns: + List of dictionaries containing term information + """ + with open(data_file, 'r', encoding='utf-8') as f: + if data_file.endswith('.json'): + data = json.load(f) + elif data_file.endswith(('.yml', '.yaml')): + try: + import yaml + data = yaml.safe_load(f) + except ImportError: + raise ImportError("PyYAML is required to parse YAML files. Install it with: pip install pyyaml") + else: + raise ValueError(f"Unsupported file format: {data_file}") + + # Normalize the data structure + if isinstance(data, list): + terms = data + elif isinstance(data, dict) and 'terms' in data: + terms = data['terms'] + else: + terms = [data] + + # Ensure all terms have required fields + for term in terms: + term.setdefault('abbreviation', '') + term.setdefault('aliases', []) + + return terms + + +def manual_term_list() -> List[Dict]: + """ + Returns a manually curated list of glossary terms. + + This is the most reliable method but requires manual maintenance. + Update this list when you add new terms to your glossary. + """ + return [ + # Core Concepts + { + 'term': 'Keyword', + 'definition': 'Named reusable action or sequence of actions in Robot Framework.', + 'abbreviation': '', + 'aliases': [] + }, + { + 'term': 'Suite', + 'definition': 'Collection of tests or tasks defined in a .robot file or directory.', + 'abbreviation': '', + 'aliases': ['Test Suite', 'Task Suite'] + }, + { + 'term': 'Test Case', + 'definition': 'Executable specification that verifies system behavior.', + 'abbreviation': '', + 'aliases': ['Test'] + }, + { + 'term': 'Task', + 'definition': 'Executable entity similar to a test case but used for automation.', + 'abbreviation': '', + 'aliases': [] + }, + + # Arguments + { + 'term': 'Argument', + 'definition': 'Value supplied to a keyword call.', + 'abbreviation': '', + 'aliases': [] + }, + { + 'term': 'Mandatory Argument', + 'definition': 'Argument without a default value that must be provided.', + 'abbreviation': '', + 'aliases': [] + }, + { + 'term': 'Optional Argument', + 'definition': 'Argument that has a default value and may be omitted.', + 'abbreviation': '', + 'aliases': [] + }, + { + 'term': 'Positional Argument', + 'definition': 'Argument provided by position in the argument list.', + 'abbreviation': '', + 'aliases': [] + }, + { + 'term': 'Named Argument', + 'definition': 'Argument provided using an explicit name=value pair.', + 'abbreviation': '', + 'aliases': [] + }, + { + 'term': 'Embedded Argument', + 'definition': 'Argument defined directly in a keyword name using ${} syntax.', + 'abbreviation': '', + 'aliases': [] + }, + { + 'term': 'Positional or Named Argument', + 'definition': 'Argument that can be set either by position or by name.', + 'abbreviation': '', + 'aliases': [] + }, + { + 'term': 'Variable Number of Positional Arguments', + 'definition': 'Optional argument marked with * that collects remaining positional values.', + 'abbreviation': '', + 'aliases': ['*varargs', '*args'] + }, + { + 'term': 'Named-Only Argument', + 'definition': 'Argument that must be provided by name (never positionally).', + 'abbreviation': '', + 'aliases': [] + }, + { + 'term': 'Free Named Argument', + 'definition': 'Catch-all argument marked with ** that gathers undefined named values.', + 'abbreviation': '', + 'aliases': ['kwargs', '**kwargs'] + }, + + # Add more terms as needed... + ] + + +def save_terms(terms: List[Dict], output_file: str, format: str = 'json'): + """ + Save extracted terms to a file. + + Args: + terms: List of term dictionaries + output_file: Path to output file + format: Output format ('json', 'python', or 'yaml') + """ + output_path = Path(output_file) + + if format == 'json': + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(terms, f, indent=2, ensure_ascii=False) + + elif format == 'python': + # Generate Python code + with open(output_path, 'w', encoding='utf-8') as f: + f.write('# Glossary terms extracted from Robot Framework RFCP Syllabus\n') + f.write('# Auto-generated file - do not edit manually\n\n') + f.write('GLOSSARY_TERMS = [\n') + for term in terms: + f.write(' {\n') + f.write(f" 'term': {repr(term['term'])},\n") + f.write(f" 'definition': {repr(term['definition'])},\n") + f.write(f" 'abbreviation': {repr(term.get('abbreviation', ''))},\n") + f.write(f" 'aliases': {repr(term.get('aliases', []))},\n") + f.write(' },\n') + f.write(']\n') + + elif format == 'yaml': + try: + import yaml + with open(output_path, 'w', encoding='utf-8') as f: + yaml.dump(terms, f, allow_unicode=True, default_flow_style=False) + except ImportError: + raise ImportError("PyYAML is required for YAML output. Install it with: pip install pyyaml") + + else: + raise ValueError(f"Unsupported format: {format}") + + print(f"Terms saved to: {output_path}") + + +def merge_aliases(terms: List[Dict]) -> List[Dict]: + """ + Post-process terms to merge "See ..." references into aliases. + + Args: + terms: List of term dictionaries + + Returns: + Processed list with aliases merged + """ + # Build a map of term names to their entries + term_map = {t['term']: t for t in terms} + + # Find and process "See ..." references + see_references = [] + for i, term in enumerate(terms): + see_match = re.match(r'See\s+(.+)', term['definition']) + if see_match: + target_term = see_match.group(1).strip() + if target_term in term_map: + # Add this term as an alias to the target + if term['term'] not in term_map[target_term]['aliases']: + term_map[target_term]['aliases'].append(term['term']) + see_references.append(i) + + # Remove "See ..." entries + for i in reversed(see_references): + terms.pop(i) + + return terms + + +def main(): + """Main function.""" + import argparse + + parser = argparse.ArgumentParser( + description='Extract glossary terms from Robot Framework RFCP Syllabus' + ) + parser.add_argument( + '--input', + help='Input file (markdown, HTML, JSON, or YAML)' + ) + parser.add_argument( + '--input-type', + choices=['markdown', 'html', 'json', 'yaml', 'manual'], + default='manual', + help='Type of input file' + ) + parser.add_argument( + '--output', + default='glossary_terms.json', + help='Output file path' + ) + parser.add_argument( + '--format', + choices=['json', 'python', 'yaml'], + default='json', + help='Output format' + ) + + args = parser.parse_args() + + # Extract terms based on input type + if args.input_type == 'manual': + terms = manual_term_list() + elif args.input_type == 'markdown': + terms = extract_from_markdown(args.input) + elif args.input_type == 'html': + with open(args.input, 'r', encoding='utf-8') as f: + html_content = f.read() + terms = extract_from_html_table(html_content) + elif args.input_type in ['json', 'yaml']: + terms = extract_from_structured_data(args.input) + + # Post-process terms + terms = merge_aliases(terms) + + # Print summary + print(f"Extracted {len(terms)} glossary terms") + print("\nSample terms:") + for term in terms[:5]: + print(f" - {term['term']}") + if term.get('aliases'): + print(f" Aliases: {', '.join(term['aliases'])}") + + # Save to file + save_terms(terms, args.output, args.format) + + +if __name__ == '__main__': + main() diff --git a/tools/glossary_linker.py b/tools/glossary_linker.py new file mode 100644 index 0000000..c4f1fb1 --- /dev/null +++ b/tools/glossary_linker.py @@ -0,0 +1,464 @@ +#!/usr/bin/env python3 +""" +Glossary Linker for Robot Framework RFCP Syllabus (v4 - Test|Task Support) + +This script automatically adds links to glossary terms throughout the documentation. + +NEW in v4: +- Handles Test|Task notation (e.g., "Test|Task Setup" → links to "Test Setup") + +FEATURES: +- Uses relative paths for Docusaurus compatibility +- Excludes YAML frontmatter (---...---) +- Excludes markdown headings (# ... ## ... ### ...) +- Only links terms in actual body content/paragraphs +- Supports Test|Task notation as approved by committee + +This prevents glossary links from appearing in: +- Sidebar navigation (generated from headings) +- Previous/Next navigation (uses page titles) +- Table of contents +""" + +import re +import os +from pathlib import Path +from typing import Dict, List, Set, Tuple +import json + + +class GlossaryLinker: + def __init__(self, docs_path: str, use_relative_paths: bool = True): + self.docs_path = Path(docs_path) + self.use_relative_paths = use_relative_paths + self.glossary_terms = {} + self.aliases = {} + + def load_glossary_terms(self, glossary_data: List[Dict]) -> None: + """Load glossary terms and their aliases from provided data.""" + for entry in glossary_data: + term = entry['term'] + slug = self._create_slug(term) + + # Store the main term + self.glossary_terms[term] = slug + + # Store abbreviations as aliases + if entry.get('abbreviation'): + abbr = entry['abbreviation'] + self.aliases[abbr] = (term, slug) + + # Store additional aliases + if entry.get('aliases'): + for alias in entry['aliases']: + self.aliases[alias] = (term, slug) + + def _create_slug(self, term: str) -> str: + """Create a URL-safe slug from a term.""" + slug = term.lower() + slug = re.sub(r'[^\w\s-]', '', slug) + slug = re.sub(r'[\s_]+', '-', slug) + slug = re.sub(r'-+', '-', slug) + slug = slug.strip('-') + return slug + + def _get_relative_path(self, from_file: Path) -> str: + """Calculate the relative path from a file to the glossary.""" + try: + rel_path = from_file.relative_to(self.docs_path) + depth = len(rel_path.parent.parts) + + if depth > 0: + prefix = '../' * depth + return f'{prefix}glossary' + else: + return './glossary' + except ValueError: + return '/docs/glossary' + + def _escape_for_regex(self, term: str) -> str: + """Escape special regex characters in term.""" + return re.escape(term) + + def _extract_frontmatter(self, content: str) -> Tuple[str, str]: + """ + Extract YAML frontmatter from content. + + Returns: + Tuple of (frontmatter, main_content) + """ + frontmatter = "" + main_content = content + + # Check for YAML frontmatter (--- ... ---) + frontmatter_pattern = r'^---\s*\n(.*?)\n---\s*\n' + match = re.match(frontmatter_pattern, content, re.DOTALL) + + if match: + frontmatter = match.group(0) + main_content = content[match.end():] + + return frontmatter, main_content + + def _create_link_patterns(self, current_file: Path) -> List[Tuple[str, str, str]]: + """Create regex patterns for finding and replacing glossary terms.""" + patterns = [] + + # Get the appropriate glossary URL for this file + if self.use_relative_paths: + glossary_url = self._get_relative_path(current_file) + else: + glossary_url = '/docs/glossary' + + # =================================================================== + # NEW: Handle Test|Task notation + # Committee approved: Test|Task something → links to Test something + # =================================================================== + test_task_mappings = [ + ('Test|Task Setup', 'Test Setup'), + ('Test|Task Teardown', 'Test Teardown'), + ('Test|Task Timeout', 'Test Timeout'), + ('Test|Task Template', 'Test Template'), + ('Test|Task Tag', 'Test Tag'), + ] + + for notation, target_term in test_task_mappings: + if target_term in self.glossary_terms: + slug = self.glossary_terms[target_term] + escaped = self._escape_for_regex(notation) + # Pattern: match "Test|Task Something" as a whole phrase + pattern = rf'(? Dict: + """Process a single markdown file and add glossary links.""" + stats = { + 'file': str(file_path.relative_to(self.docs_path)), + 'terms_linked': 0, + 'changes': [] + } + + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + original_content = content + + # Extract frontmatter + frontmatter, main_content = self._extract_frontmatter(content) + + # Get patterns for this file + patterns = self._create_link_patterns(file_path) + + # Track which terms were already linked + already_linked = set() + + # Split content into sections - CRITICAL: exclude headings + sections = self._split_content_sections(main_content) + processed_sections = [] + + for section_type, section_content in sections: + if section_type in ['code', 'heading']: + # DON'T modify code blocks or headings + processed_sections.append(section_content) + else: + # Apply patterns to text sections only + modified_content = section_content + for pattern, replacement, term_type in patterns: + matches = list(re.finditer(pattern, modified_content, re.IGNORECASE)) + if matches: + term_matched = matches[0].group(1) + if term_matched not in already_linked: + modified_content = re.sub(pattern, replacement, modified_content, count=0) + stats['terms_linked'] += len(matches) + stats['changes'].append({ + 'term': term_matched, + 'type': term_type, + 'occurrences': len(matches) + }) + already_linked.add(term_matched) + + processed_sections.append(modified_content) + + # Reconstruct content with frontmatter + new_content = frontmatter + ''.join(processed_sections) + + # Only write if content changed and not a dry run + if new_content != original_content and not dry_run: + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_content) + stats['modified'] = True + else: + stats['modified'] = False + + except Exception as e: + stats['error'] = str(e) + + return stats + + def _split_content_sections(self, content: str) -> List[Tuple[str, str]]: + """ + Split content into headings, code blocks, and text sections. + + Returns: + List of tuples: (section_type, content) + where section_type is 'heading', 'code', or 'text' + """ + sections = [] + lines = content.split('\n') + + i = 0 + while i < len(lines): + line = lines[i] + + # Check for heading (# ... ## ... ### ...) + if line.strip().startswith('#'): + # This is a heading - don't link terms here + sections.append(('heading', line + '\n')) + i += 1 + continue + + # Check for code block start + if line.strip().startswith('```'): + # Collect entire code block + code_block = [line] + i += 1 + while i < len(lines): + code_block.append(lines[i]) + if lines[i].strip().startswith('```'): + i += 1 + break + i += 1 + sections.append(('code', '\n'.join(code_block) + '\n')) + continue + + # Check for inline code or existing links in the line + if '`' in line or '[' in line: + # Split this line more carefully + processed_line = self._process_line_with_special_content(line) + sections.extend(processed_line) + i += 1 + continue + + # Regular text line + sections.append(('text', line + '\n')) + i += 1 + + return sections + + def _process_line_with_special_content(self, line: str) -> List[Tuple[str, str]]: + """ + Process a line that contains inline code or links. + Split it into code/link parts and text parts. + """ + sections = [] + current_pos = 0 + + # Pattern for inline code `...` and links [...](...) + special_pattern = r'`[^`]+`|\[([^\]]+)\]\([^)]+\)' + + for match in re.finditer(special_pattern, line): + # Add text before special content + if current_pos < match.start(): + text_part = line[current_pos:match.start()] + if text_part: + sections.append(('text', text_part)) + + # Add special content (code or link) + sections.append(('code', match.group())) + current_pos = match.end() + + # Add remaining text + if current_pos < len(line): + remaining = line[current_pos:] + if remaining: + sections.append(('text', remaining)) + + # Add newline at the end + if sections: + last_type, last_content = sections[-1] + sections[-1] = (last_type, last_content + '\n') + else: + sections.append(('text', line + '\n')) + + return sections + + def process_all_markdown_files(self, dry_run: bool = False) -> Dict: + """Process all markdown files in the docs directory.""" + overall_stats = { + 'total_files': 0, + 'modified_files': 0, + 'total_terms_linked': 0, + 'files': [] + } + + # Find all .md or .mdx files + markdown_files = list(self.docs_path.glob('**/*.md')) + list(self.docs_path.glob('**/*.mdx')) + + for md_file in markdown_files: + # Skip the glossary file itself + if 'glossary' in md_file.name.lower(): + continue + + overall_stats['total_files'] += 1 + file_stats = self.process_markdown_file(md_file, dry_run) + + if file_stats.get('modified', False): + overall_stats['modified_files'] += 1 + + overall_stats['total_terms_linked'] += file_stats.get('terms_linked', 0) + + if file_stats.get('terms_linked', 0) > 0 or file_stats.get('error'): + overall_stats['files'].append(file_stats) + + return overall_stats + + +# Comprehensive glossary data for RFCP Syllabus +GLOSSARY_DATA = [ + {'term': 'Keyword', 'definition': 'Named reusable action or sequence of actions in Robot Framework.', 'abbreviation': '', 'aliases': []}, + {'term': 'Suite', 'definition': 'Collection of tests or tasks defined in a .robot file or directory.', 'abbreviation': '', 'aliases': ['Test Suite', 'Task Suite']}, + {'term': 'Test Case', 'definition': 'Executable specification that verifies system behavior.', 'abbreviation': '', 'aliases': []}, + {'term': 'Task', 'definition': 'Executable entity for non-testing automation.', 'abbreviation': '', 'aliases': []}, + {'term': 'User Keyword', 'definition': 'Keyword defined in Robot Framework syntax.', 'abbreviation': '', 'aliases': ['Composite Keyword']}, + {'term': 'Keyword Library', 'definition': 'Collection of library keywords.', 'abbreviation': '', 'aliases': ['Library']}, + {'term': 'Resource File', 'definition': 'File containing user keywords and variables.', 'abbreviation': '', 'aliases': []}, + {'term': 'Variable', 'definition': 'Named reference to a value.', 'abbreviation': '', 'aliases': []}, + {'term': 'Argument', 'definition': 'Value supplied to a keyword call.', 'abbreviation': '', 'aliases': []}, + {'term': 'Mandatory Argument', 'definition': 'Argument without a default value.', 'abbreviation': '', 'aliases': []}, + {'term': 'Optional Argument', 'definition': 'Argument with a default value.', 'abbreviation': '', 'aliases': []}, + {'term': 'Positional Argument', 'definition': 'Argument provided by position.', 'abbreviation': '', 'aliases': []}, + {'term': 'Named Argument', 'definition': 'Argument provided using name=value pair.', 'abbreviation': '', 'aliases': []}, + {'term': 'Embedded Argument', 'definition': 'Argument defined in keyword name.', 'abbreviation': '', 'aliases': []}, + {'term': 'Positional or Named Argument', 'definition': 'Argument that can be set by position or name.', 'abbreviation': '', 'aliases': []}, + {'term': 'Variable Number of Positional Arguments', 'definition': 'Optional argument marked with * that collects remaining values.', 'abbreviation': '', 'aliases': ['*varargs', '*args']}, + {'term': 'Named-Only Argument', 'definition': 'Argument that must be provided by name.', 'abbreviation': '', 'aliases': []}, + {'term': 'Free Named Argument', 'definition': 'Catch-all argument marked with **.', 'abbreviation': '', 'aliases': ['kwargs', '**kwargs']}, + {'term': 'Keyword Interface', 'definition': 'Documented information of a keyword.', 'abbreviation': '', 'aliases': []}, + {'term': 'Argument Interface', 'definition': 'Specification of keyword arguments.', 'abbreviation': '', 'aliases': []}, + {'term': 'Return Type Hint', 'definition': 'Indication of return value type.', 'abbreviation': '', 'aliases': []}, + {'term': 'Suite Setup', 'definition': 'Keyword executed before tests in a suite.', 'abbreviation': '', 'aliases': []}, + {'term': 'Suite Teardown', 'definition': 'Keyword executed after tests in a suite.', 'abbreviation': '', 'aliases': []}, + {'term': 'Test Setup', 'definition': 'Keyword executed before a test.', 'abbreviation': '', 'aliases': ['Task Setup']}, + {'term': 'Test Teardown', 'definition': 'Keyword executed after a test.', 'abbreviation': '', 'aliases': ['Task Teardown']}, + {'term': 'Test Tag', 'definition': 'Label for categorization.', 'abbreviation': '', 'aliases': ['Task Tag']}, + {'term': 'Test Template', 'definition': 'Setting for test template.', 'abbreviation': '', 'aliases': ['Task Template']}, + {'term': 'Test Timeout', 'definition': 'Maximum execution time.', 'abbreviation': '', 'aliases': ['Task Timeout']}, + {'term': 'Keyword-Driven Specification', 'definition': 'Style using keyword call sequences.', 'abbreviation': '', 'aliases': []}, + {'term': 'Behavior-Driven Specification', 'definition': 'Style describing user perspective behavior.', 'abbreviation': '', 'aliases': []}, + {'term': 'Data-Driven Specification', 'definition': 'Style with varying input data.', 'abbreviation': '', 'aliases': []}, + {'term': 'Control Structure', 'definition': 'Statement controlling execution flow.', 'abbreviation': '', 'aliases': []}, + {'term': 'FOR Loop', 'definition': 'Structure to iterate over items.', 'abbreviation': '', 'aliases': []}, + {'term': 'WHILE Loop', 'definition': 'Structure repeating while condition is true.', 'abbreviation': '', 'aliases': []}, + {'term': 'Scalar Variable', 'definition': 'Variable with ${} syntax.', 'abbreviation': '', 'aliases': []}, + {'term': 'List Variable', 'definition': 'Variable with @{} syntax.', 'abbreviation': '', 'aliases': []}, + {'term': 'Variable Scope', 'definition': 'Visibility and lifetime of a variable.', 'abbreviation': '', 'aliases': []}, + {'term': 'Global Variable', 'definition': 'Variable with global scope.', 'abbreviation': '', 'aliases': []}, + {'term': 'Suite Variable', 'definition': 'Variable scoped to a suite.', 'abbreviation': '', 'aliases': []}, + {'term': 'Local Variable', 'definition': 'Variable scoped to execution context.', 'abbreviation': '', 'aliases': []}, + {'term': 'Built-In Variables', 'definition': 'Variables provided by Robot Framework.', 'abbreviation': '', 'aliases': []}, + {'term': 'Command Line Interface', 'definition': 'Interface to run Robot Framework.', 'abbreviation': 'CLI', 'aliases': ['Robot Framework CLI']}, + {'term': 'Generic Test Automation Architecture', 'definition': 'Layered reference architecture.', 'abbreviation': 'gTAA', 'aliases': []}, + {'term': 'Definition Layer', 'definition': 'Layer containing test data.', 'abbreviation': '', 'aliases': []}, + {'term': 'Execution Layer', 'definition': 'Layer with execution engine.', 'abbreviation': '', 'aliases': []}, + {'term': 'Adaptation Layer', 'definition': 'Layer connecting to SUT.', 'abbreviation': '', 'aliases': []}, + {'term': 'Execution Artifacts', 'definition': 'Files produced by execution.', 'abbreviation': '', 'aliases': []}, + {'term': 'Output File', 'definition': 'Machine-readable result file.', 'abbreviation': '', 'aliases': ['output.xml']}, + {'term': 'Log File', 'definition': 'Detailed HTML execution log.', 'abbreviation': '', 'aliases': ['log.html']}, + {'term': 'Report File', 'definition': 'High-level HTML summary.', 'abbreviation': '', 'aliases': ['report.html']}, + {'term': 'Pass Status', 'definition': 'Status indicating success.', 'abbreviation': '', 'aliases': []}, + {'term': 'Fail Status', 'definition': 'Status indicating failure.', 'abbreviation': '', 'aliases': []}, + {'term': 'Skip Status', 'definition': 'Status indicating skip.', 'abbreviation': '', 'aliases': []}, + {'term': 'Robot Framework Foundation', 'definition': 'Non-profit steward of Robot Framework.', 'abbreviation': '', 'aliases': []}, + {'term': 'Robot Framework® Certified Professional', 'definition': 'Foundational certification level.', 'abbreviation': 'RFCP', 'aliases': []}, + {'term': 'Robotic Process Automation', 'definition': 'Automation of business processes.', 'abbreviation': 'RPA', 'aliases': []}, + {'term': 'Behavior-Driven Development', 'definition': 'Development approach with business language.', 'abbreviation': 'BDD', 'aliases': []}, + {'term': 'Standard Library', 'definition': 'Library shipped with Robot Framework.', 'abbreviation': '', 'aliases': []}, +] + + +def main(): + """Main function.""" + import argparse + + parser = argparse.ArgumentParser(description='Add glossary links to RFCP Syllabus (with Test|Task support)') + parser.add_argument('docs_path', help='Path to docs directory') + parser.add_argument('--dry-run', action='store_true', help='Preview changes') + parser.add_argument('--use-absolute-paths', action='store_true', help='Use absolute paths') + parser.add_argument('--output', help='Statistics output file (JSON)') + + args = parser.parse_args() + + use_relative = not args.use_absolute_paths + linker = GlossaryLinker(args.docs_path, use_relative_paths=use_relative) + linker.load_glossary_terms(GLOSSARY_DATA) + + print(f"Processing: {args.docs_path}") + print(f"Dry run: {args.dry_run}") + print(f"Relative paths: {use_relative}") + print(f"Test|Task notation: ENABLED") + print() + + stats = linker.process_all_markdown_files(dry_run=args.dry_run) + + print("=" * 60) + print("SUMMARY") + print("=" * 60) + print(f"Total files: {stats['total_files']}") + print(f"Modified: {stats['modified_files']}") + print(f"Terms linked: {stats['total_terms_linked']}") + print() + + if stats['files']: + print("=" * 60) + print("DETAILS") + print("=" * 60) + for file_stats in stats['files'][:10]: # Show first 10 + print(f"\n{file_stats['file']}") + if file_stats.get('error'): + print(f" ERROR: {file_stats['error']}") + else: + print(f" Terms: {file_stats['terms_linked']}") + for change in file_stats['changes'][:3]: + print(f" - {change['term']}: {change['occurrences']}x") + if change['type'] == 'test-task-notation': + print(f" (Test|Task notation)") + + if args.output: + with open(args.output, 'w') as f: + json.dump(stats, f, indent=2) + print(f"\nStats saved: {args.output}") + + +if __name__ == '__main__': + main() diff --git a/tools/quickstart.sh b/tools/quickstart.sh new file mode 100644 index 0000000..c2f2cda --- /dev/null +++ b/tools/quickstart.sh @@ -0,0 +1,239 @@ +#!/bin/bash +# +# Quick Start Script for RFCP Syllabus Glossary Linker +# +# This script provides an easy way to run the glossary linker with common options +# + +set -e # Exit on error + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Script directory +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +LINKER="$SCRIPT_DIR/glossary_linker.py" + +# Function to print colored messages +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Function to show usage +show_usage() { + cat << EOF +Usage: $0 [OPTION] [DOCS_PATH] + +Automatically add glossary links to Robot Framework RFCP Syllabus documentation. + +OPTIONS: + test Run in test mode (dry-run) without modifying files + apply Apply changes to documentation files + single Process a single chapter (prompts for chapter number) + stats Show statistics from last run + help Show this help message + +DOCS_PATH: + Path to the documentation directory (default: ./docs) + +EXAMPLES: + $0 test # Test mode on ./docs + $0 test ../path/to/docs # Test mode on custom path + $0 apply # Apply changes to ./docs + $0 single # Process single chapter + +For more information, see README_GLOSSARY_LINKER.md +EOF +} + +# Function to check prerequisites +check_prerequisites() { + # Check if Python is available + if ! command -v python3 &> /dev/null; then + print_error "Python 3 is not installed or not in PATH" + exit 1 + fi + + # Check if glossary_linker.py exists + if [ ! -f "$LINKER" ]; then + print_error "glossary_linker.py not found in $SCRIPT_DIR" + exit 1 + fi + + print_success "Prerequisites check passed" +} + +# Function to run test mode +run_test() { + local docs_path="$1" + + print_info "Running in TEST MODE (no files will be modified)" + print_info "Processing: $docs_path" + echo "" + + python3 "$LINKER" "$docs_path" --dry-run + + echo "" + print_success "Test completed successfully" + print_info "Review the output above to see what would be changed" + print_info "If everything looks good, run: $0 apply $docs_path" +} + +# Function to apply changes +run_apply() { + local docs_path="$1" + + print_warning "This will modify files in: $docs_path" + read -p "Are you sure you want to continue? (y/N) " -n 1 -r + echo "" + + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_info "Cancelled by user" + exit 0 + fi + + print_info "Applying changes..." + echo "" + + # Create backup + local backup_dir="${docs_path}_backup_$(date +%Y%m%d_%H%M%S)" + print_info "Creating backup: $backup_dir" + cp -r "$docs_path" "$backup_dir" + + # Run the linker + python3 "$LINKER" "$docs_path" --output glossary_stats.json + + echo "" + print_success "Changes applied successfully" + print_info "Backup created at: $backup_dir" + print_info "Statistics saved to: glossary_stats.json" + echo "" + print_info "Next steps:" + echo " 1. Review the changes: git diff $docs_path" + echo " 2. Test the documentation build" + echo " 3. Commit the changes: git add $docs_path && git commit -m 'Add glossary links'" +} + +# Function to process single chapter +run_single() { + local docs_path="$1" + + echo "" + echo "Available chapters in $docs_path:" + ls -d "$docs_path"/chapter-* 2>/dev/null | sed 's/.*chapter-/ chapter-/' || echo " (no chapters found)" + echo "" + + read -p "Enter chapter number (e.g., 02): " chapter_num + + local chapter_path="$docs_path/chapter-$chapter_num" + + if [ ! -d "$chapter_path" ]; then + print_error "Chapter directory not found: $chapter_path" + exit 1 + fi + + print_info "Processing chapter $chapter_num" + echo "" + + # Run in test mode first + print_info "Step 1: Test mode" + python3 "$LINKER" "$chapter_path" --dry-run + + echo "" + read -p "Apply changes to this chapter? (y/N) " -n 1 -r + echo "" + + if [[ $REPLY =~ ^[Yy]$ ]]; then + python3 "$LINKER" "$chapter_path" + print_success "Changes applied to chapter $chapter_num" + else + print_info "No changes made" + fi +} + +# Function to show statistics +show_stats() { + if [ -f "glossary_stats.json" ]; then + print_info "Statistics from last run:" + echo "" + python3 -m json.tool glossary_stats.json + else + print_warning "No statistics file found (glossary_stats.json)" + print_info "Run with 'apply' option to generate statistics" + fi +} + +# Main script + +# Check if no arguments provided +if [ $# -eq 0 ]; then + show_usage + exit 0 +fi + +# Parse command +COMMAND="$1" +DOCS_PATH="${2:-./docs}" + +# Check prerequisites +check_prerequisites + +# Execute command +case "$COMMAND" in + test) + if [ ! -d "$DOCS_PATH" ]; then + print_error "Documentation directory not found: $DOCS_PATH" + exit 1 + fi + run_test "$DOCS_PATH" + ;; + + apply) + if [ ! -d "$DOCS_PATH" ]; then + print_error "Documentation directory not found: $DOCS_PATH" + exit 1 + fi + run_apply "$DOCS_PATH" + ;; + + single) + if [ ! -d "$DOCS_PATH" ]; then + print_error "Documentation directory not found: $DOCS_PATH" + exit 1 + fi + run_single "$DOCS_PATH" + ;; + + stats) + show_stats + ;; + + help|--help|-h) + show_usage + ;; + + *) + print_error "Unknown command: $COMMAND" + echo "" + show_usage + exit 1 + ;; +esac + +exit 0 diff --git a/website/docs/chapter-01/00_overview.md b/website/docs/chapter-01/00_overview.md index f525844..30ea28d 100644 --- a/website/docs/chapter-01/00_overview.md +++ b/website/docs/chapter-01/00_overview.md @@ -1,3 +1,4 @@ # 1 Introduction to Robot Framework -The upcoming chapters provide a concise overview of Robot Framework, including its core structure, use cases in test automation and Robotic Process Automation (RPA), and key specification styles like keyword-driven and behavior-driven testing. You'll learn about its architecture, syntax, and how test cases and tasks are organized. Additionally, the chapters explain the open-source licensing under Apache 2.0, the role of the Robot Framework Foundation in maintaining the ecosystem, and the foundational web resources available for further exploration and contributions. \ No newline at end of file +The upcoming chapters provide a concise overview of Robot Framework, including its core structure, use cases in test automation and [Robotic Process Automation](../glossary#robotic-process-automation) (RPA), and key specification styles like keyword-driven and behavior-driven testing. You'll learn about its architecture, syntax, and how test cases and tasks are organized. Additionally, the chapters explain the open-source licensing under Apache 2.0, the role of the [Robot Framework Foundation](../glossary#robot-framework-foundation) in maintaining the ecosystem, and the foundational web resources available for further exploration and contributions. + diff --git a/website/docs/chapter-01/01_purpose.md b/website/docs/chapter-01/01_purpose.md index 68f8de5..bd3ca66 100644 --- a/website/docs/chapter-01/01_purpose.md +++ b/website/docs/chapter-01/01_purpose.md @@ -52,14 +52,16 @@ Beyond traditional test levels, **Synthetic Monitoring**, also referred to as ** ## 1.1.2 Robotic Process Automation (RPA) -Robotic Process Automation (RPA) uses software bots to perform tasks and interactions normally performed by humans, without requiring changes to the underlying applications. +[Robotic Process Automation](../glossary#robotic-process-automation) (RPA) uses software bots to perform tasks and interactions normally performed by humans, without requiring changes to the underlying applications. -Robot Framework, with its keyword-driven approach, vast ecosystem of libraries, simplicity, and scalability, is widely adopted for RPA tasks. +Robot Framework, with its keyword-driven approach, vast ecosystem of libraries, simplicity, and scalability, is widely adopted for [RPA](../glossary#robotic-process-automation) tasks. Robot Framework allows users to automate most workflows using ready-made keyword libraries that provide a wide range of functionalities. These libraries can be combined and reused in user-defined keywords, making automation simple and efficient. For custom functionalities or more complex tasks, Robot Framework also offers the flexibility to create custom keyword libraries using Python, enabling advanced use cases and seamless integration with unique systems. -Common use cases of RPA with Robot Framework include: +Common use cases of [RPA](../glossary#robotic-process-automation) with Robot Framework include: - **Data extraction and manipulation**: Automating data transfers and processing between systems. - **Task / Process automation**: Automating tasks such as form submissions, clicks, and file operations across web or desktop applications. + + diff --git a/website/docs/chapter-01/02_architecture.md b/website/docs/chapter-01/02_architecture.md index 4d93df2..fc6ed0a 100644 --- a/website/docs/chapter-01/02_architecture.md +++ b/website/docs/chapter-01/02_architecture.md @@ -1,6 +1,6 @@ # 1.2 Architecture of Robot Framework -Robot Framework is an open-source automation framework that allows you to build automation scripts for testing and RPA (Robotic Process Automation). +Robot Framework is an open-source automation framework that allows you to build automation scripts for testing and [RPA](../glossary#robotic-process-automation) (Robotic Process Automation). It focuses on providing a keyword-driven or behavior-driven approach, making the automation easy to understand and maintain. However, it is not a full-stack solution that encompasses all layers of automation. Instead, it provides a flexible platform where different tools, libraries, and integrations handle specific tasks to implement a flexible automation solution. @@ -13,7 +13,7 @@ Instead, it provides a flexible platform where different tools, libraries, and i :::K1[LO-1.2.1] -Recall the layers of the Generic Test Automation Architecture (gTAA) and their corresponding components in Robot Framework +Recall the layers of the [Generic Test Automation Architecture](../glossary#generic-test-automation-architecture) (gTAA) and their corresponding components in Robot Framework ::: @@ -65,7 +65,7 @@ It includes: However, Robot Framework **does not** include: -- Keyword libraries to control systems under test/RPA. +- [Keyword](../glossary#keyword) libraries to control systems under test/[RPA](../glossary#robotic-process-automation). Such as: - Web front-end automation libraries. @@ -102,3 +102,5 @@ Robot Framework itself does not have any external dependencies, but additional t + + diff --git a/website/docs/chapter-01/03_syntax.md b/website/docs/chapter-01/03_syntax.md index 7ddc924..d32721b 100644 --- a/website/docs/chapter-01/03_syntax.md +++ b/website/docs/chapter-01/03_syntax.md @@ -69,7 +69,7 @@ Create User With Admin Rights ## 1.3.1 What are Test Cases / Tasks? In Robot Framework, **Test Cases** (**Tests**) or **Tasks** are executable entities that serve a specific purpose and are organized into suites. -A **Test** is synonymous with a **Test Case**, while **Task**, technically being the same, is used in RPA mode, where the automation is not focused on testing but on automating business processes. +A **Test** is synonymous with a **Test Case**, while **Task**, technically being the same, is used in [RPA](../glossary#robotic-process-automation) mode, where the automation is not focused on testing but on automating business processes. Tests or Tasks have a body made up of **keyword calls** and Robot Framework statements like **IF** or **VAR**, which represent the actions or steps executed during the test or task execution. These keywords make the automation modular, maintainable, reusable, and readable. @@ -95,7 +95,7 @@ This structure allows for logical grouping and organization of tests and tasks, :::K2[LO-1.3.3] -Explain the difference between User Keywords and Library Keywords +Explain the difference between User Keywords and [Library](../glossary#keyword-library) Keywords ::: @@ -104,7 +104,7 @@ Explain the difference between User Keywords and Library Keywords Tests or Tasks are constructed using **Keywords**, which represent specific actions or sequences of actions to be performed. -**Keywords** in Robot Framework follow the concepts used in Behavior-Driven Development (BDD) and Keyword-Driven Testing. +**Keywords** in Robot Framework follow the concepts used in [Behavior-Driven Development](../glossary#behavior-driven-development) (BDD) and [Keyword](../glossary#keyword)-Driven Testing. **Definition**: one or more words used as a reference to a specific set of actions intended to be performed during the execution of one or more tests or tasks. @@ -122,7 +122,7 @@ Login User Execute Login ``` -2. **Library Keywords**: Typically written in Python, but they may also be implemented using other technologies. These keywords typically interact with the system under test (SUT) or the system to be controlled by RPA, or execute specific actions such as calculations or conversions. From the viewpoint of Robot Framework, such keywords are not composed of other keywords and do form the lowest level of keywords. Therefore, they are also referred to as **low-level keywords**. In other literature, such keywords are also called **Technical Keywords** or **Atomic Keywords**. +2. **Library Keywords**: Typically written in Python, but they may also be implemented using other technologies. These keywords typically interact with the system under test (SUT) or the system to be controlled by [RPA](../glossary#robotic-process-automation), or execute specific actions such as calculations or conversions. From the viewpoint of Robot Framework, such keywords are not composed of other keywords and do form the lowest level of keywords. Therefore, they are also referred to as **low-level keywords**. In other literature, such keywords are also called **Technical Keywords** or **Atomic Keywords**. A **User Keyword** consists of a **name**, optional **arguments**, and a **body** of keyword calls that may invoke other user keywords, library keywords, or other statements such as variable definitions or flow control. @@ -147,8 +147,8 @@ Recall the difference between Resource Files and Libraries and their artifacts While tests and tasks are organized into suites, **keywords** are organized into **Resource Files** and **Keyword Libraries**. -- **Resource Files**: Contain **User Keywords** and are also used to organize the importing of libraries and the definition of variables. These are considered to be part of the test|task data in the *Definition Layer*. -- **Keyword Libraries**: Contain **Library Keywords**, which are typically implemented in Python or other technologies and, except for the standard libraries, are not part of Robot Framework itself. They can be either custom-made or third-party libraries implemented by the Robot Framework community. These are considered to be part of the *Adaptation Layer*. +- **Resource Files**: Contain **User Keywords** and are also used to organize the importing of libraries and the definition of variables. These are considered to be part of the test|task data in the *[Definition Layer](../glossary#definition-layer)*. +- **Keyword Libraries**: Contain **Library Keywords**, which are typically implemented in Python or other technologies and, except for the standard libraries, are not part of Robot Framework itself. They can be either custom-made or third-party libraries implemented by the Robot Framework community. These are considered to be part of the *[Adaptation Layer](../glossary#adaptation-layer)*. Central resource files and libraries allow the separation of concerns, making the automation more modular and reusable across multiple suites, tests or tasks. @@ -157,3 +157,5 @@ The concepts of organizing are fundamental to working with Robot Framework and c + + diff --git a/website/docs/chapter-01/04_styles.md b/website/docs/chapter-01/04_styles.md index 3a7b2a8..87d9ff0 100644 --- a/website/docs/chapter-01/04_styles.md +++ b/website/docs/chapter-01/04_styles.md @@ -12,11 +12,11 @@ Recall the three specification styles of Robot Framework :::: Specification styles define how tests or tasks are structured, focusing on how actions and verifications are described. -While **Keyword-Driven Testing (KDT)** and **Behavior-Driven Development (BDD)** are commonly associated with testing, the principles behind these styles are adaptable to other forms of automation, such as RPA. +While **Keyword-Driven Testing (KDT)** and **Behavior-Driven Development (BDD)** are commonly associated with testing, the principles behind these styles are adaptable to other forms of automation, such as [RPA](../glossary#robotic-process-automation). Both styles can be mixed, even within the same test or task, but it is strongly recommended to have separate styles for separate purposes and not mix them within the same body. -One practical solution would be to define acceptance test cases that cover users' expectations in a declarative *Behavior-Driven Style*, while using keywords that are implemented in an imperative *Keyword-Driven style*. -Further system level :term[test cases]{term="Test Case"}, that are not covering acceptance criteria could be written in a *Keyword-Driven style*. +One practical solution would be to define acceptance test cases that cover users' expectations in a declarative *Behavior-Driven Style*, while using keywords that are implemented in an imperative *[Keyword](../glossary#keyword)-Driven style*. +Further system level :term[test cases]{term="[Test Case](../glossary#test-case)"}, that are not covering acceptance criteria could be written in a *[Keyword](../glossary#keyword)-Driven style*. The approach of both styles is different in that way, that the *Behavior-Driven Style* is a **declarative** specification, @@ -38,7 +38,7 @@ with the other two styles, to define the data that is used in the automation. :::K2[LO-1.4.1] -Understand the basic concepts of Keyword-Driven Specification +Understand the basic concepts of [Keyword-Driven Specification](../glossary#keyword-driven-specification) ::: @@ -73,7 +73,7 @@ Flow and data can be parsed separately by the consumer. :::K2[LO-1.4.2] -Understand the basic concepts of Behavior-Driven Specification +Understand the basic concepts of [Behavior-Driven Specification](../glossary#behavior-driven-specification) ::: @@ -94,8 +94,8 @@ Opening Foundation Page ``` The prefixes `Given`, `When`, `Then`, `And` and `But` are basically ignored by Robot Framework if a keyword is found matching the rest of the name. -A key difference between Robot Framework's behavior-driven style and BDD frameworks like **Cucumber** or most others is the ability in Robot Framework to use **multiple keyword layers**. -In other BDD frameworks the code that implements a sentence like `Given "robotframework.org" is open.` is referred to as a step definition. +A key difference between Robot Framework's behavior-driven style and [BDD](../glossary#behavior-driven-development) frameworks like **Cucumber** or most others is the ability in Robot Framework to use **multiple keyword layers**. +In other [BDD](../glossary#behavior-driven-development) frameworks the code that implements a sentence like `Given "robotframework.org" is open.` is referred to as a step definition. Step definitions are written in a programming language (typically Java, JavaScript, Ruby, or Python) and map natural language steps from a Gherkin feature file to code. Therefore there are no multiple layers of keywords that can be logged into execution protocols. Robot Framework allows you to create **user keywords** that can further call other user or library keywords, providing greater flexibility, modularity and much more detailed logging. @@ -108,7 +108,7 @@ Robot Framework allows you to create **user keywords** that can further call oth :::K1[LO-1.4.3] -Recall the differences between Keyword-Driven and Behavior-Driven Specification +Recall the differences between Keyword-Driven and [Behavior-Driven Specification](../glossary#behavior-driven-specification) ::: @@ -141,7 +141,7 @@ Both styles can be applied within Robot Framework, offering flexibility dependin :::K1[LO-1.4.4] -Recall the purpose of Data-Driven Specification +Recall the purpose of [Data-Driven Specification](../glossary#data-driven-specification) ::: @@ -155,7 +155,7 @@ While in **Robotic Process Automation (RPA)**, the data used in an automation workflow is typically acquired dynamically from an external source, in testing, the data is specifically chosen to cover different scenarios or cases. Therefore, this method of defining data combinations -statically in the suite files is normally not applicable to RPA. +statically in the suite files is normally not applicable to [RPA](../glossary#robotic-process-automation). The purpose of **Data-Driven Testing** is to automate the same sequence of actions or scenario with different sets of input and/or expected output data. @@ -173,6 +173,8 @@ Robot Framework offers a convenient feature for this approach through **Test Tem - **Clarity**: Keeps the test logic separate from the data, making it easier to manage large data sets. - **Scalability**: Suitable for scenarios where the same functionality needs to be tested under various conditions, such as verifying form inputs or performing calculations with different values. -See [3.4 Using Data-Driven Specification](chapter-03/04_datadriven.md) for more details and examples on Data-Driven Specification. +See [3.4 Using Data-Driven Specification](chapter-03/04_datadriven.md) for more details and examples on [Data-Driven Specification](../glossary#data-driven-specification). + + diff --git a/website/docs/chapter-01/05_organization.md b/website/docs/chapter-01/05_organization.md index 7fd7bd9..12bab15 100644 --- a/website/docs/chapter-01/05_organization.md +++ b/website/docs/chapter-01/05_organization.md @@ -30,7 +30,7 @@ This licensing structure encourages broad usage and contribution while maintaini :::K1[LO-1.5.2] -List and recall the key objectives and organizational form of the Robot Framework Foundation +List and recall the key objectives and organizational form of the [Robot Framework Foundation](../glossary#robot-framework-foundation) ::: @@ -46,7 +46,7 @@ Key objectives of the foundation include: - **Platform Maintenance**: The foundation is responsible for maintaining key infrastructure, such as the official website, GitHub repositories, and community platforms. These resources are crucial to sustaining a healthy ecosystem and fostering collaboration among users and contributors. -- **Community Support and Events**: The foundation plays a central role in organizing **RoboCon**, the annual Robot Framework User Conference, which brings together users, developers, and contributors to share knowledge and insights. Additionally, it helps to disseminate knowledge about test automation and RPA through community events and documentation efforts. +- **Community Support and Events**: The foundation plays a central role in organizing **RoboCon**, the annual Robot Framework User Conference, which brings together users, developers, and contributors to share knowledge and insights. Additionally, it helps to disseminate knowledge about test automation and [RPA](../glossary#robotic-process-automation) through community events and documentation efforts. - **Funding of Ecosystem Projects**: Whenever possible, the foundation finances open-source projects that are proposed by community members, aiming to support broader ecosystem development and innovation. @@ -75,3 +75,5 @@ These include: - **[robotframework.org](https://robotframework.org/)**: The main page providing an overview, documentation, and access to resources. - **[github.com/robotframework](https://github.com/robotframework)**: The official repository for the framework's source code and other components. + + diff --git a/website/docs/chapter-02/00_overview.md b/website/docs/chapter-02/00_overview.md index 9c43a64..957b52d 100644 --- a/website/docs/chapter-02/00_overview.md +++ b/website/docs/chapter-02/00_overview.md @@ -9,4 +9,5 @@ the role of libraries and resource files, and how to import them. Additionally, it delves into the core syntax of Robot Framework, focusing on how keywords are defined and used, the types of keyword arguments, -and how keyword documentation is interpreted to ensure clarity and maintainability. \ No newline at end of file +and how keyword documentation is interpreted to ensure clarity and maintainability. + diff --git a/website/docs/chapter-02/01_suitefile.md b/website/docs/chapter-02/01_suitefile.md index a673144..87ca3e3 100644 --- a/website/docs/chapter-02/01_suitefile.md +++ b/website/docs/chapter-02/01_suitefile.md @@ -19,7 +19,7 @@ If the path to a single file is given as **Root Suite** directly to Robot Framew If a directory path is given, starting at this location, Robot Framework will parse all `*.robot` files and directories within this path. Robot Framework analyzes all containing files and determines if they contain test cases or tasks. If they do, they are considered **Suite Files** or **Low-Level Suites**. -All directories that either directly or indirectly contain a Suite File are considered **Suites Directories** or **Higher-Level Suites**. +All directories that either directly or indirectly contain a [Suite](../glossary#suite) File are considered **Suites Directories** or **Higher-Level Suites**. The ordering of suites during execution is, by default, defined by their name and hierarchy. All files and directories, which are suites in one directory, are considered on the same level and are executed in case-insensitive alphabetical order. @@ -65,7 +65,7 @@ Example: :::K1[LO-2.1.1] -Recall the conditions and requirements for a file to be considered a Suite file +Recall the conditions and requirements for a file to be considered a [Suite](../glossary#suite) file ::: @@ -75,7 +75,7 @@ Robot Framework parses files with the extension `.robot` and searches for test c A parsed file that contains at least one test case or task is called a **Suite File**. -A Suite File **either** contains `*** Test Cases ***` (in Test Suites) **or** `*** Tasks ***` (in Task Suites), but it CANNOT contain both types simultaneously. +A Suite File **either** contains `*** Test Cases ***` (in Test Suites) **or** `*** Tasks ***` (in [Task](../glossary#task) Suites), but it CANNOT contain both types simultaneously. @@ -164,7 +164,7 @@ Recall the purpose of the `*** Variables ***` section. This section is used to define suite variables that are used in the suite or its tests|tasks or inside their keywords. The most common use case is to define these variables as constants that contain a static value during execution. -This can either be a default value, that may be overwritten by globally defined variables via the Command Line Interface (CLI) or a constant value that is used in multiple places in the suite. +This can either be a default value, that may be overwritten by globally defined variables via the [Command Line Interface](../glossary#command-line-interface) (CLI) or a constant value that is used in multiple places in the suite. In some cases, these variables are also dynamically reassigned during the execution of the suite, but this is not recommended and should be avoided if possible, because this may lead to test|task runtime dependancies and errors caused by these side-effects that are hard to debug and find. @@ -194,7 +194,7 @@ A suite file must contain either a `*** Test Cases ***` or a `*** Tasks ***` sec See [2.6 Writing Test|Task and Calling Keywords](chapter-02/06_writing_test.md) for more information about the `*** Test Cases ***` or `*** Tasks ***` section. - + ### 2.1.2.4 Introduction to `*** Keywords ***` Section @@ -233,3 +233,5 @@ All content in this section is ignored by Robot Framework and is not executed or + + diff --git a/website/docs/chapter-02/02_suitefile_syntax.md b/website/docs/chapter-02/02_suitefile_syntax.md index dd49fa1..e8c420c 100644 --- a/website/docs/chapter-02/02_suitefile_syntax.md +++ b/website/docs/chapter-02/02_suitefile_syntax.md @@ -17,7 +17,7 @@ Understand the basic syntax of test cases and tasks. :::: -Suite files and resource files share the same syntax, however they differ in their capabilities. +[Suite](../glossary#suite) files and resource files share the same syntax, however they differ in their capabilities. Resource files are explained in more detail in [2.4.2 Resource Files](chapter-02/04_keyword_imports.md#242-resource-files) [3.1 Resource File Structure](chapter-03/01_resource_file.md). @@ -271,7 +271,7 @@ In the test case body, some keyword calls have arguments that are separated by t The following tests will be executed in the order they are defined in the suite file. First, the `Login User With Password` test case will be executed, followed by the `Denied Login With Wrong Password` test case. -Example Suite File Content: +Example [Suite](../glossary#suite) File Content: ```robotframework title="robot_files/TestSuite.robot" *** Settings *** Documentation A suite for valid and invalid login tests. @@ -301,3 +301,5 @@ Denied Login With Wrong Password + + diff --git a/website/docs/chapter-02/03_executing.md b/website/docs/chapter-02/03_executing.md index 61fad30..1b5cc05 100644 --- a/website/docs/chapter-02/03_executing.md +++ b/website/docs/chapter-02/03_executing.md @@ -4,7 +4,7 @@ :::K1[LO-2.3] -Recall the three components of the Robot Framework CLI. +Recall the three components of the [Robot Framework CLI](../glossary#command-line-interface). ::: @@ -112,19 +112,19 @@ Recall the four different status labels used by Robot Framework. Robot Framework uses different status labels to indicate the result of an execution: -On Suite, Test Case, Task and Keyword Level: +On [Suite](../glossary#suite), [Test Case](../glossary#test-case), [Task](../glossary#task) and [Keyword](../glossary#keyword) Level: - **`PASS`**: Indicates that the item was successfully executed without unexpected errors. - **`FAIL`**: Shows that the item encountered an error and did not pass. - **`SKIP`**: Indicates that the item was intentionally skipped, either by tagging or during execution, typically because some condition was not met. -Additional Keyword Status: +Additional [Keyword](../glossary#keyword) Status: - **`NOT RUN`**: Refers to keywords that were not executed during execution, e.g. due to previous failure or conditions. `SKIP` is explained in more detail in later chapters. -**Atomic elements** like Library Keywords or Robot Framework language statements do define their own status. +**Atomic elements** like [Library](../glossary#keyword-library) Keywords or Robot Framework language statements do define their own status. -**Composite elements** like suites (composed of tests|tasks), tests|tasks (composed of keywords) and User Keywords (composed of Library Keywords and Robot Framework statements) do define their status based on the status of their child elements. +**Composite elements** like suites (composed of tests|tasks), tests|tasks (composed of keywords) and User Keywords (composed of [Library](../glossary#keyword-library) Keywords and Robot Framework statements) do define their status based on the status of their child elements. ### 2.3.3.1 PASS @@ -144,7 +144,7 @@ This status is used if an element was executed successfully without any errors o **Atomic elements** are `PASS` if they were executed successfully without reporting an error by raising an exception. **Composite elements** are `PASS` if all their executed body elements are pass. -E.g. in case of User Keywords this means that if all keywords or Robot Framework language statements that were directly called by that User Keyword were `PASS` the User Keyword itself is considered `PASS`. +E.g. in case of User Keywords this means that if all keywords or Robot Framework language statements that were directly called by that [User Keyword](../glossary#user-keyword) were `PASS` the [User Keyword](../glossary#user-keyword) itself is considered `PASS`. Library Keywords like `Run Keyword And Expect Error`, from BuiltIn Library, do `PASS` if the keyword they are internally calling does raise an error with the expected message or type. @@ -199,3 +199,5 @@ There are basically two kinds of logging information in Robot Framework. Log messages can be written with different levels of severity (i.e. `INFO`, `DEBUG`, `TRACE`, `WARN` or `ERROR`). Which levels are written to the log can be controlled by the log level of an execution. Further information in later chapters. + + diff --git a/website/docs/chapter-02/04_keyword_imports.md b/website/docs/chapter-02/04_keyword_imports.md index 5d10225..61b6dfd 100644 --- a/website/docs/chapter-02/04_keyword_imports.md +++ b/website/docs/chapter-02/04_keyword_imports.md @@ -123,7 +123,7 @@ If a relative path is given, the path is resolved relative to the data file that If an **absolute path** is given, the resource file or library is searched for at the given path. If a **relative path** is given, the resource file or library is searched for relative to the data file that is importing it and then relative to the Python *module search path*. -This *module search path* is defined by the Python interpreter that executes Robot Framework and can be influenced by the environment variable `PYTHONPATH` or by using the CLI-Argument `--pythonpath` when executing `robot`. +This *module search path* is defined by the Python interpreter that executes Robot Framework and can be influenced by the environment variable `PYTHONPATH` or by using the [CLI](../glossary#command-line-interface)-[Argument](../glossary#argument) `--pythonpath` when executing `robot`. For **path separators**, it is strongly recommended to always use forward slashes (`/`), and even on Windows, not to use backslashes (`\`). This is because backslashes are used as escape characters in Robot Framework, which can cause issues when used in paths. Forward slashes are supported on all operating systems when used in Robot Framework. @@ -137,3 +137,5 @@ That path needs to be defined when executing Robot Framework but can lead to mor + + diff --git a/website/docs/chapter-02/05_keyword_interface.md b/website/docs/chapter-02/05_keyword_interface.md index ac13d0a..3a48a15 100644 --- a/website/docs/chapter-02/05_keyword_interface.md +++ b/website/docs/chapter-02/05_keyword_interface.md @@ -11,14 +11,14 @@ Understand the structure of keyword interfaces and how to interpret keyword docu :::: -Library Keywords and User Keywords that are defined in a resource file should have a documentation text that describes what the keyword does and how it should be used. +[Library](../glossary#keyword-library) Keywords and User Keywords that are defined in a resource file should have a documentation text that describes what the keyword does and how it should be used. Robot Framework is capable of generating **Keyword Documentation** files that contains a library- or resource-documentation, all keywords, their argument interfaces, and their documentation texts. This documentation file can be generated with the `libdoc` command and can be used to provide a reference for users who want to use the keywords. -Basically all standard and external 3rd party libraries offer these Keyword Documentations as online available HTML pages. +Basically all standard and external 3rd party libraries offer these [Keyword](../glossary#keyword) Documentations as online available HTML pages. -Robot Framework offers the Keyword Documentation of its Standard Libraries at https://robotframework.org/robotframework . +Robot Framework offers the [Keyword](../glossary#keyword) Documentation of its Standard Libraries at https://robotframework.org/robotframework . @@ -70,7 +70,7 @@ All of them can be called positionally or by name. ![Run Process Keyword Documentation](/img/Run_Process_Docs.png) -This keyword has one Mandatory Argument `command` which can be called positionally or by name. +This keyword has one [Mandatory Argument](../glossary#mandatory-argument) `command` which can be called positionally or by name. The latter two arguments are optional. The argument `arguments` is a :term[Variable Number of Positional Arguments] and can only be set by position. @@ -118,20 +118,20 @@ The more business oriented keywords are the less arguments they typically have. Keyword arguments can be grouped into different argument kinds. On the one hand you can group them by their definition attributes and on the other hand by their usage kind. -The relevant distinction of usage kinds is between using :term[Positional Arguments]{term="Positional Argument"}, :term[Named Arguments]{term="Named Argument"}, or :term[Embedded Arguments]{term="Embedded Argument"}. +The relevant distinction of usage kinds is between using :term[Positional Arguments]{term="[Positional Argument](../glossary#positional-argument)"}, :term[Named Arguments]{term="[Named Argument](../glossary#named-argument)"}, or :term[Embedded Arguments]{term="[Embedded Argument](../glossary#embedded-argument)"}. How to use them is described in [2.6 Writing Test|Task and Calling Keywords](chapter-02/06_writing_test.md). Another important information is if an argument is mandatory or optional. See the next two sections for more information about these two kinds of arguments. Most arguments can either be set by their position or by their name. -But there are some kinds of arguments that can only be set positionally, like :term[Variable Number of Positional Arguments], or only be set named, like :term[Named-Only Arguments]{term="Named-Only Argument"} or :term[Free Named Arguments]{term="Free Named Argument"}. +But there are some kinds of arguments that can only be set positionally, like :term[Variable Number of Positional Arguments], or only be set named, like :term[Named-Only Arguments]{term="[Named-Only Argument](../glossary#named-only-argument)"} or :term[Free Named Arguments]{term="[Free Named Argument](../glossary#free-named-argument)"}. The order is as follows: -1. :term[Positional or Named Arguments]{term="Positional or Named Argument"} (can be mandatory or optional) +1. :term[Positional or Named Arguments]{term="[Positional or Named Argument](../glossary#positional-or-named-argument)"} (can be mandatory or optional) 2. :term[Variable Number of Positional Arguments] (optional) -3. :term[Named-Only Arguments]{term="Named-Only Argument"} (can be mandatory or optional) -4. :term[Free Named Arguments]{term="Free Named Argument"} (optional) +3. :term[Named-Only Arguments]{term="Named-Only [Argument](../glossary#argument)"} (can be mandatory or optional) +4. :term[Free Named Arguments]{term="[Free Named Argument](../glossary#free-named-argument)"} (optional) ### 2.5.2.1 Mandatory Arguments @@ -189,7 +189,7 @@ Arguments that have a default value can be omitted when the keyword is called, c These arguments are listed after the mandatory arguments in the argument interface. Default values are defined and represented in the docs by the equal sign `=` after the argument name and a value after that. -Also :term[Variable Number of Positional Arguments], represented with a single star (`*`) prefix, and :term[Free Named Arguments]{term="Free Named Argument"}, represented with a double star (`**`) prefix are optional arguments. +Also :term[Variable Number of Positional Arguments], represented with a single star (`*`) prefix, and :term[Free Named Arguments]{term="Free [Named Argument](../glossary#named-argument)"}, represented with a double star (`**`) prefix are optional arguments. E.g. the argument `msg` in the `Should Be Equal` keyword documentation has the default value `None` and `ignore_case` has the default value `False`. @@ -205,13 +205,13 @@ Omitting some optional arguments but still using others is possible independent :::K1[LO-2.5.2.3] -Recall the concept of keywords with embedded arguments used in Behavior-Driven Specification and how they are documented. +Recall the concept of keywords with embedded arguments used in [Behavior-Driven Specification](../glossary#behavior-driven-specification) and how they are documented. ::: :::: -Keywords can include arguments embedded directly into their names, a feature primarily used for Behavior-Driven Development (BDD). +Keywords can include arguments embedded directly into their names, a feature primarily used for [Behavior-Driven Development](../glossary#behavior-driven-development) (BDD). Embedded arguments are mandatory and must be provided in the exact position defined within the keyword name. Keyword names include arguments defined using the scalar variable syntax with dollar and curly braces (`${var_name}`). @@ -223,7 +223,7 @@ Example keyword names are: - `the page title should be ${exp_title}` - `the url should be ${exp_url}` -Example Test Case: +Example [Test Case](../glossary#test-case): ```robotframework *** Test Cases *** Foundation Page should be Accessible @@ -235,7 +235,7 @@ Foundation Page should be Accessible The optional prefixes `Given`, `When`, `Then`, `And` and `But` are basically ignored by Robot Framework if a keyword is found matching the rest of the name including the embedded arguments. In the example :term[test case] some keywords are designed so that the arguments are surrounded by double quotes (`"`) for better visibility. -A mix of embedded arguments and "normal" arguments is possible to fully support BDD. +A mix of embedded arguments and "normal" arguments is possible to fully support [BDD](../glossary#behavior-driven-development). In the keyword documentation the embedded arguments are written in variable syntax with dollar-curly-braces (`${var_name}`) to indicate that they are not part of the keyword name but are arguments. They can also be defined using regular expressions to allow for more complex argument structures, which is not part of this syllabus. @@ -253,7 +253,7 @@ Recall how "Positional or Named Arguments" are marked in the documentation and t :::: Except for "Positional-Only Arguments", which are not part of this syllabus, -all arguments that are positioned before :term[Variable Number of Positional Arguments], :term[Named-Only Arguments]{term="Named-Only Argument"}, or :term[Free Named Arguments]{term="Free Named Argument"} in the argument interface of a keyword are :term[Positional or Named Arguments]{term="Positional or Named Argument"}. +all arguments that are positioned before :term[Variable Number of Positional Arguments], :term[Named-Only Arguments]{term="[Named-Only Argument](../glossary#named-only-argument)"}, or :term[Free Named Arguments]{term="Free Named [Argument](../glossary#argument)"} in the argument interface of a keyword are :term[Positional or Named Arguments]{term="[Positional or Named Argument](../glossary#positional-or-named-argument)"}. As their name states, they can be set either by their position or by their name, but not by both at the same time for one argument. If an argument shall be set by its position, all preceding arguments must be set by their position as well. @@ -269,7 +269,7 @@ They are not specially marked in the keyword documentation with any prefix, beca :::K1[LO-2.5.2.5] -Recall how "Variable Number of Positional Arguments" are marked in the documentation and their use case. +Recall how "[Variable Number of Positional Arguments](../glossary#variable-number-of-positional-arguments)" are marked in the documentation and their use case. ::: @@ -369,7 +369,7 @@ However, the actual implementation of the keyword may expect a different type of If an argument type is defined and Robot Framework has a matching converter function available, that can convert the given type to the expected type, the conversion is tried automatically. If the conversion fails, the keyword call will fail with an error message before the actual keyword code is executed. Robot Framework brings some built-in converters for common types like integer, float, boolean, list, dictionary, etc. -Library developers can also register their own converters for none-supported types. +[Library](../glossary#keyword-library) developers can also register their own converters for none-supported types. Defining types for arguments is nowadays the recommended way to let Robot Framework convert the given arguments to the expected type, however it is optional. @@ -466,3 +466,5 @@ Should Be Equal ${x} expected ignore_case=True formatter=repr + + diff --git a/website/docs/chapter-02/06_writing_test.md b/website/docs/chapter-02/06_writing_test.md index 1180f2c..f98f202 100644 --- a/website/docs/chapter-02/06_writing_test.md +++ b/website/docs/chapter-02/06_writing_test.md @@ -12,7 +12,7 @@ Understand how to call imported keywords and how to structure keyword calls. A typical test case or task is a sequence of keyword calls that are executed in a specific order. As learned before these keywords need to be imported into the suite or resource file before they can be used. -When using keywords in a test|task or User Keyword, it is important to indent the keyword calls correctly. +When using keywords in a test|task or [User Keyword](../glossary#user-keyword), it is important to indent the keyword calls correctly. With the exception of returning values, which are described in Chapter 3, the name of the keyword is the first element of the keyword call followed by the arguments that are separated by two or more spaces. @@ -21,7 +21,7 @@ The following example shows different ways to call imported keywords in a test c The keyword name should be written as defined in the keyword documentation and may have single spaces or other special characters in it. After the keyword name the arguments are set. All arguments are separated by multiple spaces from the keyword name and from each other and can also include single spaces. -Argument values are stripped from leading and trailing spaces, but spaces within the argument value are preserved. +[Argument](../glossary#argument) values are stripped from leading and trailing spaces, but spaces within the argument value are preserved. If an argument shall contain more than one consecutive spaces or start or end with spaces, the spaces must be escaped by a backslash `\` to prevent them from being interpreted as a part of a "multi-space-separator". @@ -76,7 +76,7 @@ Understand the concept of how to set argument values positionally. :::: When calling keywords, arguments can often be set positionally in the order they are defined in the keyword documentation. -An exception to this are :term[Named-Only Arguments]{term="Named-Only Argument"} and :term[Free Named Arguments]{term="Free Named Argument"} that can only be set by their name. +An exception to this are :term[Named-Only Arguments]{term="[Named-Only Argument](../glossary#named-only-argument)"} and :term[Free Named Arguments]{term="[Free Named Argument](../glossary#free-named-argument)"} that can only be set by their name. However, only using positional values can lead to poor readability as you can see in the previous example: `Mixed Positional Arguments` Some keywords do not have an obvious order of arguments. @@ -128,13 +128,13 @@ Understand the concept of named arguments and how to set argument values by thei :::: -Keyword Calls with non-obvious arguments should use named argument calls if possible. +[Keyword](../glossary#keyword) Calls with non-obvious arguments should use named argument calls if possible. Also setting one optional argument but leaving the others at their default value is an indication to use named arguments. Named arguments are set by their name followed by an equal sign `=` and the value of the argument. All named arguments must be set after the positional arguments are set but can be set in any order. -Equal signs are valid argument values and could therefore be misinterpreted as named arguments, if the text before the equal sign is an existing argument name or if :term[Free Named Arguments]{term="Free Named Argument"} are available at the called keyword. +Equal signs are valid argument values and could therefore be misinterpreted as named arguments, if the text before the equal sign is an existing argument name or if :term[Free Named Arguments]{term="Free [Named Argument](../glossary#named-argument)"} are available at the called keyword. To prevent that, an equal sign in argument values can be escaped by a backslash `\`. Example of escaping conflicting equal signs: @@ -161,7 +161,7 @@ Recall how to use embedded arguments. :::: -Embedded Arguments are mostly used in Behavior-Driven Development (BDD) using Robot Frameworks Behavior-Driven Specification style. +Embedded Arguments are mostly used in [Behavior-Driven Development](../glossary#behavior-driven-development) (BDD) using Robot Frameworks [Behavior-Driven Specification](../glossary#behavior-driven-specification) style. Embedded Arguments are part of the keyword name as described in [2.5.2.3 Embedded Arguments](chapter-02/05_keyword_interface.md#2523-embedded-arguments). @@ -169,4 +169,5 @@ When calling keywords with embedded arguments, all characters that are at the po See the example in section [2.5.2.3 Embedded Arguments](chapter-02/05_keyword_interface.md#2523-embedded-arguments). -See also [2.5.2.3 Embedded Arguments](chapter-02/05_keyword_interface.md#2523-embedded-arguments) for more information about how to use embedded arguments. \ No newline at end of file +See also [2.5.2.3 Embedded Arguments](chapter-02/05_keyword_interface.md#2523-embedded-arguments) for more information about how to use embedded arguments. + diff --git a/website/docs/chapter-03/00_overview.md b/website/docs/chapter-03/00_overview.md index ba07811..58df8c7 100644 --- a/website/docs/chapter-03/00_overview.md +++ b/website/docs/chapter-03/00_overview.md @@ -1,3 +1,5 @@ # 3 Keyword Design, Variables, and Resource Files -This chapter introduces the essential components of Robot Framework: **Keywords**, **Variables**, and **Resource Files**. These building blocks allow users to create reusable, structured, and maintainable automation solutions. Understanding these concepts is critical for developing efficient automation in both testing and RPA contexts. +This chapter introduces the essential components of Robot Framework: **Keywords**, **Variables**, and **Resource Files**. These building blocks allow users to create reusable, structured, and maintainable automation solutions. Understanding these concepts is critical for developing efficient automation in both testing and [RPA](../glossary#robotic-process-automation) contexts. + + diff --git a/website/docs/chapter-03/01_resource_file.md b/website/docs/chapter-03/01_resource_file.md index 5bbc0ce..e7e28b1 100644 --- a/website/docs/chapter-03/01_resource_file.md +++ b/website/docs/chapter-03/01_resource_file.md @@ -47,7 +47,7 @@ The allowed sections in recommended order are: Additional settings are: - `Keyword Tags` to set tags for all keywords in the resource file. - defining and using Keyword tags is not part of this syllabus. + defining and using [Keyword](../glossary#keyword) tags is not part of this syllabus. Other settings available in suites are not available in resource files. @@ -65,3 +65,5 @@ The allowed sections in recommended order are: + + diff --git a/website/docs/chapter-03/02_variables.md b/website/docs/chapter-03/02_variables.md index 16e94e5..fefaafc 100644 --- a/website/docs/chapter-03/02_variables.md +++ b/website/docs/chapter-03/02_variables.md @@ -60,7 +60,7 @@ Variables in Robot Framework are defined by three attributes: - **Delimiter**: `{}` to enclose the variable name. - **Variable Name**: The string that addresses the variable. i.e. just the `variable_name` or more advanced access ways. -Variable names are case-insensitive and as keywords, containing single spaces and underscores are ignored when matching variable names. +[Variable](../glossary#variable) names are case-insensitive and as keywords, containing single spaces and underscores are ignored when matching variable names. Robot Framework supports Unicode and allows the use of special characters and even Emojis in variable names. In case these prefixes followed by a curly brace opening (`${`) should be used as characters in a normal string and not as a variable, @@ -122,7 +122,7 @@ Variables created in this section: Because two or more spaces are used to separate elements in a row, all values are stripped of leading and trailing spaces, identical to arguments of keyword calls (see [2.2.4 Escaping of Control Characters](chapter-02/02_suitefile_syntax.md#224-escaping-of-control-characters) to be able to define these spaces. -Variable values in Robot Framework can include other variables, and their values will be concatenated at runtime when the line is executed. +[Variable](../glossary#variable) values in Robot Framework can include other variables, and their values will be concatenated at runtime when the line is executed. This means that when a variable is used within another variable's value, the final value is resolved by replacing the variables with their actual content during execution. Variables defined in the `*** Variables ***` section are recommended to be named in uppercase to distinguish them from local variables defined in test cases or keywords. @@ -468,3 +468,5 @@ Examples and more details on variable scope, such as `TEST` and `GLOBAL` scope c + + diff --git a/website/docs/chapter-03/03_user_keyword.md b/website/docs/chapter-03/03_user_keyword.md index 7a5f757..f0c473a 100644 --- a/website/docs/chapter-03/03_user_keyword.md +++ b/website/docs/chapter-03/03_user_keyword.md @@ -56,18 +56,18 @@ The names of User Keywords should be descriptive and clear, reflecting the purpo Well-named keywords make tests more readable and easier to understand. Robot Framework supports Unicode and allows the use of special characters and even Emojis in keyword names. -Keyword names are case-insensitive and can include single spaces. +[Keyword](../glossary#keyword) names are case-insensitive and can include single spaces. Also spaces and underscores will be ignored when matching keyword names. So the keywords `Login To System`, and `log_into_system` are considered identical. To identify keywords that shall be executed, Robot Framework uses a matching algorithm that is case-insensitive and ignores spaces and underscores. - If then a full match is found, that keyword is used. -- If no full match is found, the prefixes `Given`, `When`, `Then`, `And`, and `But` (case-insensitive), which are used in Behavior-Driven Specification style, are removed from the called keyword name to find a match. +- If no full match is found, the prefixes `Given`, `When`, `Then`, `And`, and `But` (case-insensitive), which are used in [Behavior-Driven Specification](../glossary#behavior-driven-specification) style, are removed from the called keyword name to find a match. - If still no match is found, Robot Framework tries to match the name with keywords that have embedded arguments. -By default, if not explicitly defined by the library developers, all Library Keywords are named in **Title Case** with capital letters at the beginning of each word, and spaces between words. +By default, if not explicitly defined by the library developers, all [Library](../glossary#keyword-library) Keywords are named in **Title Case** with capital letters at the beginning of each word, and spaces between words. -Project may choose a different naming convention for User Keywords, but it is recommended to be consistent across the project for User Keyword names. +Project may choose a different naming convention for User Keywords, but it is recommended to be consistent across the project for [User Keyword](../glossary#user-keyword) names. They are defined without indentation, and the subsequent lines until the next unindented line are considered the body of the keyword. The following topics explain how to structure the body of a keyword. @@ -266,7 +266,7 @@ Describe how embedded arguments are replaced by actual values during keyword exe :::K2[LO-3.3.5.3-2] -Understand the role of embedded arguments in Behavior-Driven Development (BDD) style. +Understand the role of embedded arguments in [Behavior-Driven Development](../glossary#behavior-driven-development) (BDD) style. ::: @@ -350,7 +350,7 @@ the user ${action} ### 3.3.5.4 Other Argument Kinds -Other argument kinds like :term[Named-Only Arguments]{term="Named-Only Argument"}, :term[Free Named Arguments]{term="Free Named Argument"}, or +Other argument kinds like :term[Named-Only Arguments]{term="[Named-Only Argument](../glossary#named-only-argument)"}, :term[Free Named Arguments]{term="[Free Named Argument](../glossary#free-named-argument)"}, or :term[Variable Number of Positional Arguments] should be known, but their definition and usage are not part of this syllabus. @@ -374,7 +374,7 @@ Use the `RETURN` statement to return values from a user keyword and assign it to :::: -The `RETURN` statement (case-sensitive) in Robot Framework is used to return values from a User Keyword +The `RETURN` statement (case-sensitive) in Robot Framework is used to return values from a [User Keyword](../glossary#user-keyword) to be used in further test steps or stored in variables. This allows test execution to pass data between different keywords. @@ -441,7 +441,7 @@ Recall the naming conventions for user keywords. When defining User Keywords, it is recommended to follow conventions to ensure consistency and readability across the project. These may be taken from community best practices or defined within the project team. -Keyword Conventions should contain agreements on: +[Keyword](../glossary#keyword) Conventions should contain agreements on: - **Naming Case**: Which case shall be used? (e.g. `Title Case`, `camelCase`, `snake_case`, `kebab-case`, or `Sentence case`, etc. ) (from a readability perspective, `Title Case` or `Sentence case` are recommended) - **Grammatical Form/Mood**: Which form shall be used for actions and verifications/assertions? (e.g. `Imperative` for both like `Click Button`, `Verify Text`. Or e.g. `Declarative`/`Indicative` for assertions like `Text Should Be`, `Element Should Be Visible`) - **Word/Character Count**: How many words or characters shall be used in a keyword name? (e.g. less than 7 words) @@ -453,3 +453,5 @@ Keyword Conventions should contain agreements on: + + diff --git a/website/docs/chapter-03/04_datadriven.md b/website/docs/chapter-03/04_datadriven.md index 42e8d37..e6ec565 100644 --- a/website/docs/chapter-03/04_datadriven.md +++ b/website/docs/chapter-03/04_datadriven.md @@ -5,7 +5,7 @@ :::K2[LO-3.4] -Understand the basic concept and syntax of Data-Driven Specification +Understand the basic concept and syntax of [Data-Driven Specification](../glossary#data-driven-specification) ::: @@ -25,7 +25,7 @@ Understand how to define and use test|task templates :::K1[LO-3.4.1-2] -Recall the differences between the two different approaches to define Data-Driven Specification +Recall the differences between the two different approaches to define [Data-Driven Specification](../glossary#data-driven-specification) ::: @@ -129,3 +129,5 @@ However, this approach has also its drawbacks: + + diff --git a/website/docs/chapter-03/05_advanced_importing.md b/website/docs/chapter-03/05_advanced_importing.md index be27581..1287aea 100644 --- a/website/docs/chapter-03/05_advanced_importing.md +++ b/website/docs/chapter-03/05_advanced_importing.md @@ -104,9 +104,9 @@ This is typically global behavior like internal timeouts, connection settings to If this is possible, the library documentation will have an `Importing` section directly before the list of keywords. -Library importing arguments are used in the same way as keyword calls with arguments. +[Library](../glossary#keyword-library) importing arguments are used in the same way as keyword calls with arguments. If possible, it is recommended to set the arguments as named arguments to make usage more readable and future-proof. -These arguments follow the Library path or name, separated by multiple spaces. +These arguments follow the [Library](../glossary#keyword-library) path or name, separated by multiple spaces. Example with the [Telnet library](https://robotframework.org/robotframework/latest/libraries/Telnet.html#Importing): ```robotframework @@ -194,3 +194,5 @@ Using Remote Libraries DeviceAPI.Verify Contact 15 1 ``` + + diff --git a/website/docs/chapter-04/00_overview.md b/website/docs/chapter-04/00_overview.md index def9ade..3596978 100644 --- a/website/docs/chapter-04/00_overview.md +++ b/website/docs/chapter-04/00_overview.md @@ -4,4 +4,5 @@ As a Robot Framework automation project expands, the increasing number of tests| This chapter explores advanced structuring and execution techniques to effectively manage this complexity and control the execution flow. We will cover methods for error handling and cleaning up after failed tests|tasks using **Teardowns**, as well as preparing individual or multiple suites and tests|tasks for execution with **Setups**. -Additionally, filtering subsets of tests|tasks based on tags will be discussed, which is essential for managing test|task execution efficiently. \ No newline at end of file +Additionally, filtering subsets of tests|tasks based on tags will be discussed, which is essential for managing test|task execution efficiently. + diff --git a/website/docs/chapter-04/01_setups.md b/website/docs/chapter-04/01_setups.md index b7a8f18..733ea3d 100644 --- a/website/docs/chapter-04/01_setups.md +++ b/website/docs/chapter-04/01_setups.md @@ -21,7 +21,7 @@ Recall the different levels where a Setup can be defined Setups in Robot Framework are used to prepare the environment or system for execution or to verify that the requirements/preconditions needed for execution are met. They can be defined at the suite, test|task, or keyword level and are executed before the respective scope begins execution. -A **Setup** is a single keyword with potential argument values that is called before all other keywords; or before tests|tasks in Suite Setup. +A **Setup** is a single keyword with potential argument values that is called before all other keywords; or before tests|tasks in [Suite Setup](../glossary#suite-setup). Examples of typical use cases for Setups are: - Establishing connections to databases or services. @@ -38,13 +38,13 @@ Examples of typical use cases for Setups are: :::K1[LO-4.1.1-1] -Recall key characteristics, benefits, and syntax of Suite Setup +Recall key characteristics, benefits, and syntax of [Suite](../glossary#suite) Setup ::: :::K2[LO-4.1.1-2] -Understand when Suite Setup is executed and used +Understand when [Suite Setup](../glossary#suite-setup) is executed and used ::: @@ -54,7 +54,7 @@ A **Suite Setup** is executed before any tests|tasks or child suites within the It is used to prepare the environment or perform actions that need to occur before the entire suite runs. Since it is only executed once before all tests|tasks or child suites, it can save time, rather than executing the action for each test|task individually. -**Key characteristics of Suite Setup:** +**Key characteristics of [Suite](../glossary#suite) Setup:** - Suite Setup is a single keyword call with potential argument values. - Executed before any tests|tasks and child suites in the suite. - If the Suite Setup fails, all tests|tasks in the suite and its child suites are marked as failed, and they are not executed. @@ -82,29 +82,29 @@ Suite Setup Initialize Environment dataset=Config_C3 :::K1[LO-4.1.2-1] -Recall key characteristics, benefits, and syntax of Test Setup +Recall key characteristics, benefits, and syntax of [Test Setup](../glossary#test-setup) ::: :::K2[LO-4.1.2-2] -Understand when Test|Task Setup is executed and used +Understand when Test|[Task](../glossary#task) Setup is executed and used ::: :::: -A **Test|Task Setup** is executed before a single test|task runs. +A **Test|[Task](../glossary#task) Setup** is executed before a single test|task runs. It is used to prepare the specific conditions required for that test|task. -You can define a default Test|Task Setup in the `*** Settings ***` section of the suite using the `Test Setup`|`Task Setup` setting. +You can define a default Test|[Task Setup](../glossary#test-setup) in the `*** Settings ***` section of the suite using the `Test Setup`|`Task Setup` setting. This setup will be applied to all tests|tasks within the suite unless overridden and executed before each test|task. Individual tests|tasks can override the default setup by specifying their own `[Setup]` setting within the test|task. To disable the setup for a specific test|task, you can set `[Setup] NONE`, which means that no setup will be executed for that test|task. -**Key characteristics of Test|Task Setup:** -- Test|Task Setup is a single keyword call with potential argument values. +**Key characteristics of [Test|Task Setup](../glossary#test-setup):** +- Test|[Task Setup](../glossary#test-setup) is a single keyword call with potential argument values. - Executed before the test|task starts. - If the Test|Task Setup fails, the test|task is marked as failed, and its body, including its main keywords, is not executed. - Can be set globally for all tests|tasks in a suite and overridden locally. @@ -146,7 +146,7 @@ No Setup Test :::K1[LO-4.1.3] -Recall key characteristics and syntax of Keyword Setup +Recall key characteristics and syntax of [Keyword](../glossary#keyword) Setup ::: @@ -155,7 +155,7 @@ Recall key characteristics and syntax of Keyword Setup A **Keyword Setup** is executed before the body of a user keyword is executed. It allows for preparation steps specific to that keyword or ensures that the keyword's requirements are met before execution. -**Key characteristics of Keyword Setup:** +**Key characteristics of [Keyword](../glossary#keyword) Setup:** - Keyword Setup is a single keyword call with potential argument values. - Executed before the keyword's body. - If the Keyword Setup fails, the keyword's body is not executed. @@ -178,3 +178,5 @@ Process Data + + diff --git a/website/docs/chapter-04/02_teardowns.md b/website/docs/chapter-04/02_teardowns.md index eefb7e7..ba1423b 100644 --- a/website/docs/chapter-04/02_teardowns.md +++ b/website/docs/chapter-04/02_teardowns.md @@ -44,13 +44,13 @@ reducing dependencies between tests|tasks and improving the reliability of your :::K1[LO-4.2.1-1] -Recall key characteristics, benefits, and syntax of Suite Teardown +Recall key characteristics, benefits, and syntax of [Suite Teardown](../glossary#suite-teardown) ::: :::K2[LO-4.2.1-2] -Understand when Suite Teardown is executed and used +Understand when [Suite](../glossary#suite) Teardown is executed and used ::: @@ -58,12 +58,12 @@ Understand when Suite Teardown is executed and used A **Suite Teardown** is executed after all tests|tasks and all child suites in a suite have been executed. -The Suite Teardown is executed regardless of the outcome of the tests|tasks within the suite, even if the suite setup fails. +The [Suite Teardown](../glossary#suite-teardown) is executed regardless of the outcome of the tests|tasks within the suite, even if the suite setup fails. -**Key characteristics of Suite Teardown:** +**Key characteristics of [Suite](../glossary#suite) Teardown:** - Suite Teardown is a single keyword call with potential argument values. - Executed after all tests|tasks and child suites have completed. -- Runs even if the Suite Setup fails or any test|task within the suite fails. +- Runs even if the [Suite Setup](../glossary#suite-setup) fails or any test|task within the suite fails. - If the Suite Teardown fails, all tests|tasks in the suite are marked as failed in reports and logs. - All keywords within the Suite Teardown are executed, even if one of them fails, ensuring all cleanup actions are attempted. @@ -86,23 +86,23 @@ Suite Teardown Close All Resources force=True :::K1[LO-4.2.2-1] -Recall key characteristics, benefits, and syntax of Test|Task Teardown +Recall key characteristics, benefits, and syntax of Test|[Task](../glossary#task) Teardown ::: :::K2[LO-4.2.2-2] -Understand when Test|Task Teardown is executed and used +Understand when Test|[Task Teardown](../glossary#test-teardown) is executed and used ::: :::: -A **Test|Task Teardown** is executed after a single test|task body has been executed. +A **Test|[Task](../glossary#task) Teardown** is executed after a single test|task body has been executed. It is used for cleaning up actions specific to that test|task. -The Test|Task Teardown is executed regardless of the test|task's outcome, even if the test|task's setup fails. +The [Test|Task Teardown](../glossary#test-teardown) is executed regardless of the test|task's outcome, even if the test|task's setup fails. -In Robot Framework, you can define a default Test|Task Teardown in the `*** Settings ***` section of the suite using the `Test Teardown`|`Task Teardown` setting. +In Robot Framework, you can define a default Test|[Task Teardown](../glossary#test-teardown) in the `*** Settings ***` section of the suite using the `Test Teardown`|`Task Teardown` setting. This default teardown will be applied to all tests|tasks within the suite unless overridden. Individual tests|tasks can override the default teardown by specifying their own `[Teardown]` setting within the test|task. @@ -113,7 +113,7 @@ It is recommended to define the local `[Teardown]` setting as the last line of t **Key characteristics of Test|Task Teardown:** - Test|Task Teardown is a single keyword call with potential argument values. - Executed after the test|task has been executed, regardless of its status. -- Runs even if the Test|Task Setup fails. +- Runs even if the Test|[Task Setup](../glossary#test-setup) fails. - If the Test|Task Teardown fails, the test|task is marked as failed in reports and logs. - All keywords within the Test|Task Teardown are executed, even if one of them fails. - Can be set globally for all tests|tasks in a suite and overridden locally. @@ -158,7 +158,7 @@ No Teardown Test :::K1[LO-4.2.3] -Recall key characteristics, benefits, and syntax of Keyword Teardown +Recall key characteristics, benefits, and syntax of [Keyword](../glossary#keyword) Teardown ::: @@ -170,7 +170,7 @@ ensuring that any resources used within the keyword are properly released indepe For better readability, it should be written as the last line of a keyword. -**Key characteristics of Keyword Teardown:** +**Key characteristics of [Keyword](../glossary#keyword) Teardown:** - Keyword Teardown is a single keyword call with potential argument values. - Executed after the keyword body has been executed, regardless of its status. - Runs even if the keyword's setup fails. @@ -194,3 +194,5 @@ Process Data + + diff --git a/website/docs/chapter-04/03_init_files.md b/website/docs/chapter-04/03_init_files.md index 2a6d59d..a0cc75b 100644 --- a/website/docs/chapter-04/03_init_files.md +++ b/website/docs/chapter-04/03_init_files.md @@ -37,7 +37,7 @@ Initialization files enable you to: :::K2[LO-4.3.2] -Understand the execution order of Suite Setup and Suite Teardown in Initialization Files and their sub-suites and tests|tasks +Understand the execution order of [Suite Setup](../glossary#suite-setup) and [Suite Teardown](../glossary#suite-teardown) in Initialization Files and their sub-suites and tests|tasks ::: @@ -45,8 +45,8 @@ Understand the execution order of Suite Setup and Suite Teardown in Initializati As previously explained, **Suite Setup** and **Suite Teardown** are used to prepare and clean up the environment before and after a suite's execution. Initialization files provide a centralized place to define these setups and teardowns for all sub-suites and their tests|tasks within a directory structure. -Thus, it is possible to define one Suite Setup that is executed at the very start of the execution before any other Suite Setup, Test|Task Setup, and Test|Task is executed. -The Suite Teardown of an initialization file is executed after all sub-suites in the directory and their tests|tasks have been completed. +Thus, it is possible to define one [Suite](../glossary#suite) Setup that is executed at the very start of the execution before any other [Suite](../glossary#suite) Setup, Test|[Task](../glossary#task) Setup, and Test|[Task](../glossary#task) is executed. +The [Suite Teardown](../glossary#suite-teardown) of an initialization file is executed after all sub-suites in the directory and their tests|tasks have been completed. @@ -84,7 +84,7 @@ The following sections are allowed in initialization files: - **`*** Keywords ***` Section (optional)**: - Define keywords that are available to the initialization file for Suite Setup, Suite Teardown, Test Setup, or Test Teardown. + Define keywords that are available to the initialization file for [Suite Setup](../glossary#suite-setup), Suite Teardown, [Test Setup](../glossary#test-setup), or [Test Teardown](../glossary#test-teardown). - **`*** Comments ***` Section (optional)**: @@ -125,3 +125,5 @@ Cleanup Environment + + diff --git a/website/docs/chapter-04/04_tags.md b/website/docs/chapter-04/04_tags.md index 5115927..166be72 100644 --- a/website/docs/chapter-04/04_tags.md +++ b/website/docs/chapter-04/04_tags.md @@ -5,7 +5,7 @@ :::K1[LO-4.4] -Recall the purpose of Test|Task Tags in Robot Framework +Recall the purpose of Test|[Task](../glossary#task) Tags in Robot Framework ::: @@ -34,7 +34,7 @@ Recall the syntax and different ways to assign tags to tests|tasks Tags can be assigned to tests|tasks in several ways: -1. **At the Suite Level** using the `Test Tags` setting in the `*** Settings ***` section or in an initialization file (`__init__.robot`). +1. **At the [Suite](../glossary#suite) Level** using the `Test Tags` setting in the `*** Settings ***` section or in an initialization file (`__init__.robot`). This assigns tags to all tests|tasks within the suite: ```robotframework @@ -44,7 +44,7 @@ Tags can be assigned to tests|tasks in several ways: This will assign the tags `smoke` and `regression` to all tests|tasks in the suite. -2. **At the Test|Task Level** using the `[Tags]` setting within individual tests|tasks. These tags are added in addition to any suite-level tags: +2. **At the Test|[Task](../glossary#task) Level** using the `[Tags]` setting within individual tests|tasks. These tags are added in addition to any suite-level tags: ```robotframework *** Test Cases *** @@ -70,7 +70,7 @@ Tags can be assigned to tests|tasks in several ways: This test|task will have a tag `environment:production`. -4. **By Keyword `Set Tags` or `Remove Tags`** to dynamically assign or remove tags during test|task execution: +4. **By [Keyword](../glossary#keyword) `Set Tags` or `Remove Tags`** to dynamically assign or remove tags during test|task execution: See [BuiltIn](https://robotframework.org/robotframework/latest/libraries/BuiltIn.html#Set%20Tags) library documentation for more information. @@ -162,3 +162,5 @@ Using own tags with this prefix may lead to unexpected behavior in test executio + + diff --git a/website/docs/chapter-04/05_skip.md b/website/docs/chapter-04/05_skip.md index b4b54f4..55a550b 100644 --- a/website/docs/chapter-04/05_skip.md +++ b/website/docs/chapter-04/05_skip.md @@ -22,7 +22,7 @@ In addition to `PASS` and `FAIL`, Robot Framework introduces the `SKIP` status t **Reasons to Use SKIP** - **Temporary Exclusion of Tests|Tasks**: To prevent tests|tasks with known issues from running until the issue is resolved. -- **Conditional Execution**: To skip tests|tasks dynamically based on runtime conditions, e.g., if a Suite Setup detects an issue. +- **Conditional Execution**: To skip tests|tasks dynamically based on runtime conditions, e.g., if a [Suite Setup](../glossary#suite-setup) detects an issue. - **Unsupported Scenarios**: To mark tests|tasks as skipped in environments where they cannot run, while still ensuring they are logged as such. @@ -59,7 +59,7 @@ Therefore skip is better for documenting that a specific test|task was not execu Tests|tasks can be skipped dynamically within their execution with the `Skip` keyword based on runtime conditions. The `Skip` keyword does stop the execution of a test|task and mark it as skipped with a custom message. -If a Test|Task Teardown exists, it will be executed. +If a Test|[Task](../glossary#task) Teardown exists, it will be executed. ## 4.5.3 Automatically Skipping Failed Tests @@ -73,3 +73,5 @@ Tests|tasks can be automatically marked as skipped if they fail: - **Reserved Tag `robot:skip-on-failure`**: Tag tests|tasks to skip automatically on failure. + + diff --git a/website/docs/chapter-05/00_overview.md b/website/docs/chapter-05/00_overview.md index be5fba1..09d1872 100644 --- a/website/docs/chapter-05/00_overview.md +++ b/website/docs/chapter-05/00_overview.md @@ -2,4 +2,5 @@ This chapter introduces more advanced constructs of Robot Framework. These topics are often not needed for simple automation cases but can be very useful in more complex situations. -Although it is not expected that Robot Framework Certified Professionals will be able to use them, it is important to be aware of the possibilities and to understand the basic concepts. \ No newline at end of file +Although it is not expected that Robot Framework Certified Professionals will be able to use them, it is important to be aware of the possibilities and to understand the basic concepts. + diff --git a/website/docs/chapter-05/01_advanced_variables.md b/website/docs/chapter-05/01_advanced_variables.md index 133198b..a974ad3 100644 --- a/website/docs/chapter-05/01_advanced_variables.md +++ b/website/docs/chapter-05/01_advanced_variables.md @@ -6,7 +6,7 @@ Robot Framework also offers multiple ways to create different kinds of values an However, the built-in language support is limited to the basic [3.2.2.2 Primitive Data Types](chapter-03/02_variables.md#3222-primitive-data-types), [3.2.2.3 List Variable Definition](chapter-03/02_variables.md#3223-list-variable-definition), and [3.2.2.4 Dictionary Variable Definition](chapter-03/02_variables.md#3224-dictionary-variable-definition). -This chapter provides more advanced knowledge about the different variable scopes, lists, dictionaries, their syntax, and some background on the most important Built-In Variables. +This chapter provides more advanced knowledge about the different variable scopes, lists, dictionaries, their syntax, and some background on the most important [Built-In Variables](../glossary#built-in-variables). Understanding the **priority** and **scope** of variables in Robot Framework is crucial for effective test automation. Variables can be defined in multiple places and ways, and their availability and precedence depend on where and how they are created. @@ -154,7 +154,7 @@ Recall how to define suite variables and where they can be accessed - Set during the execution of a suite using the `VAR` syntax with the `scope=SUITE` argument. (dynamic) - **Usage**: Useful for sharing data among tests/tasks within the same suite or configuring suite-specific settings or setting default values for global variables. -Suite scope is not recursive; variables in a higher-level suite, e.g. defined in [4.3 Initialization Files](chapter-04/03_init_files.md), are not available in lower-level suites. Use resource files to share variables across suites. +[Suite](../glossary#suite) scope is not recursive; variables in a higher-level suite, e.g. defined in [4.3 Initialization Files](chapter-04/03_init_files.md), are not available in lower-level suites. Use resource files to share variables across suites. Variables with a suite scope are generally statically defined or imported variables, but they can also be created dynamically during the execution of a suite. In this latter case, they have a higher priority than statically defined variables and can shadow or overwrite them. @@ -163,7 +163,7 @@ If a variable is defined in the `*** Variables ***` section of a suite file and If a global variable is defined using the command line, and a suite-level variable with the same name is dynamically defined, the suite variable now shadows the global variable and has higher priority as long as the suite is in scope. Once the suite is finished or a sub-suite is executed, the global variable returns to scope with higher priority. **Recommendation**: -Suite variables should be defined using uppercase letters, like `${SUITE_VARIABLE}`, to distinguish them from local variables. These variables should be defined in the `*** Variables ***` section of the suite file, even if they are dynamically overwritten during execution, so they are visible in the editor or IDE and can be used for auto-completion and static code analysis. +[Suite](../glossary#suite) variables should be defined using uppercase letters, like `${SUITE_VARIABLE}`, to distinguish them from local variables. These variables should be defined in the `*** Variables ***` section of the suite file, even if they are dynamically overwritten during execution, so they are visible in the editor or IDE and can be used for auto-completion and static code analysis. ### 5.1.2.3 . Test|Task Scope @@ -182,12 +182,12 @@ Recall how to define test|task variables and where they can be accessed - Created during test execution using the `VAR` syntax with the `scope=TEST` or `scope=TASK` argument. (dynamic) - **Usage**: Appropriate for data that is specific to a single test|task. -Test|Task variables cannot be created in suite setup or teardown, nor can they be imported. Test|Task scope variables are not available in other tests|tasks, even within the same suite. +Test|[Task](../glossary#task) variables cannot be created in suite setup or teardown, nor can they be imported. Test|[Task](../glossary#task) scope variables are not available in other tests|tasks, even within the same suite. They can only be created dynamically, so they have higher priority than suite or global variables while in scope. Once a test|task is finished, the variables are no longer available. If they have shadowed a suite or global variable, that variable returns to scope. **Recommendation**: -Test|Task variables should be used only when there is a clear need to share data across multiple keywords within a single test|task and when this is known by all team members. +Test|[Task](../glossary#task) variables should be used only when there is a clear need to share data across multiple keywords within a single test|task and when this is known by all team members. Otherwise, it is better to use local variables. Editor and IDE support for these variables is limited, so they should be used with caution. @@ -207,7 +207,7 @@ Recall how to define local variables and where they can be accessed - **Creation**: - Variables assigned by keyword return values. - Variables defined using the `VAR` syntax (optional: with `scope=LOCAL`) within a keyword or test|task. - - Keyword arguments. + - [Keyword](../glossary#keyword) arguments. - **Usage**: Commonly used to temporarily store data and pass it to other keywords. Local variables are the most commonly used variables in Robot Framework and have the fewest side effects. They should be preferred over other variable scopes unless there is an explicit need to share data across scope boundaries. @@ -430,7 +430,7 @@ Recall that Robot Framework provides access to execution information via Built-I Robot Framework has a set of built-in variables that can be used in test cases, keywords, and other places. Some examples are: -| Variable | Description | +| [Variable](../glossary#variable) | Description | |--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------| | `${EMPTY}` | An empty string. | | `${SPACE}` | A single space character. | @@ -441,7 +441,7 @@ Robot Framework has a set of built-in variables that can be used in test cases, Additionally, suite-related or test|task-related variables are available. These variables can have different values during test execution, and some are not available at all times. Altering the value of these variables does not affect the original values. -| Variable | Description | +| [Variable](../glossary#variable) | Description | |--------------------------|------------------------------------------------| | `${SUITE_NAME}` | The name of the current suite. | | `${SUITE_SOURCE}` | The path to the file where the current suite is defined. | @@ -455,3 +455,5 @@ These variables can be used in test cases, keywords, and other places to access + + diff --git a/website/docs/chapter-05/02_control_structures.md b/website/docs/chapter-05/02_control_structures.md index 8d66052..7c55de0 100644 --- a/website/docs/chapter-05/02_control_structures.md +++ b/website/docs/chapter-05/02_control_structures.md @@ -298,3 +298,5 @@ Get Older Participants END RETURN ${older_participants} ``` + + diff --git a/website/docs/example-exam/Example-exam.mdx b/website/docs/example-exam/Example-exam.mdx index f2e196f..fdf6b77 100644 --- a/website/docs/example-exam/Example-exam.mdx +++ b/website/docs/example-exam/Example-exam.mdx @@ -2,6 +2,8 @@ import Quiz from '@site/src/components/Quiz/Quiz'; # Example Questions -This example exam should give you the oportunity to check you knowledge and to get an impression what kind of questions may be asked in the real examination for RFCP®. +This example exam should give you the oportunity to check you knowledge and to get an impression what kind of questions may be asked in the real examination for [RFCP](../glossary#robot-framework-certified-professional)®. + + diff --git a/website/docs/learning_objectives.md b/website/docs/learning_objectives.md index e0832b2..6eb3d9f 100644 --- a/website/docs/learning_objectives.md +++ b/website/docs/learning_objectives.md @@ -3,22 +3,22 @@ | --- | --- | --- | | [`LO-1.1`](chapter-01/01_purpose.md) | K1 | Recall the two main use cases of Robot Framework | | [`LO-1.1.1`](chapter-01/01_purpose.md#111-test-automation) | K1 | Recall the test levels Robot Framework is mostly used for | -| [`LO-1.2.1`](chapter-01/02_architecture.md#121-robot-framework-and-the-gtaa-generic-test-automation-architecture) | K1 | Recall the layers of the Generic Test Automation Architecture (gTAA) and their corresponding components in Robot Framework | +| [`LO-1.2.1`](chapter-01/02_architecture.md#121-robot-framework-and-the-gtaa-generic-test-automation-architecture) | K1 | Recall the layers of the [Generic Test Automation Architecture](./glossary#generic-test-automation-architecture) (gTAA) and their corresponding components in Robot Framework | | [`LO-1.2.2`](chapter-01/02_architecture.md#122-what-is-robot-framework--what-it-is-not) | K1 | Recall what is part of Robot Framework and what is not | | [`LO-1.2.3`](chapter-01/02_architecture.md#123-technology--prerequisites) | K1 | Recall the technology Robot Framework is built on and the prerequisites for running it | | [`LO-1.3`](chapter-01/03_syntax.md) | K1 | Recall the key attributes of the syntax that makes Robot Framework simple and human-readable | -| [`LO-1.3.3`](chapter-01/03_syntax.md#133-what-are-keywords) | K2 | Explain the difference between User Keywords and Library Keywords | +| [`LO-1.3.3`](chapter-01/03_syntax.md#133-what-are-keywords) | K2 | Explain the difference between User Keywords and [Library](./glossary#keyword-library) Keywords | | [`LO-1.3.4`](chapter-01/03_syntax.md#134-resource-files--libraries) | K1 | Recall the difference between Resource Files and Libraries and their artifacts | | [`LO-1.4`](chapter-01/04_styles.md) | K1 | Recall the three specification styles of Robot Framework | -| [`LO-1.4.1`](chapter-01/04_styles.md#141-keyword-driven-specification) | K2 | Understand the basic concepts of Keyword-Driven Specification | -| [`LO-1.4.2`](chapter-01/04_styles.md#142-behavior-driven-specification) | K2 | Understand the basic concepts of Behavior-Driven Specification | -| [`LO-1.4.3`](chapter-01/04_styles.md#143-comparing-keyword-driven-and-behavior-driven-specification) | K1 | Recall the differences between Keyword-Driven and Behavior-Driven Specification | -| [`LO-1.4.4`](chapter-01/04_styles.md#144-data-driven-specification) | K1 | Recall the purpose of Data-Driven Specification | +| [`LO-1.4.1`](chapter-01/04_styles.md#141-keyword-driven-specification) | K2 | Understand the basic concepts of [Keyword-Driven Specification](./glossary#keyword-driven-specification) | +| [`LO-1.4.2`](chapter-01/04_styles.md#142-behavior-driven-specification) | K2 | Understand the basic concepts of [Behavior-Driven Specification](./glossary#behavior-driven-specification) | +| [`LO-1.4.3`](chapter-01/04_styles.md#143-comparing-keyword-driven-and-behavior-driven-specification) | K1 | Recall the differences between [Keyword](./glossary#keyword)-Driven and [Behavior-Driven Specification](./glossary#behavior-driven-specification) | +| [`LO-1.4.4`](chapter-01/04_styles.md#144-data-driven-specification) | K1 | Recall the purpose of [Data-Driven Specification](./glossary#data-driven-specification) | | [`LO-1.5.1`](chapter-01/05_organization.md#151-open-source-license) | K1 | Recall the type of open-source license under which Robot Framework is distributed | -| [`LO-1.5.2`](chapter-01/05_organization.md#152-about-the-robot-framework-foundation) | K1 | List and recall the key objectives and organizational form of the Robot Framework Foundation | +| [`LO-1.5.2`](chapter-01/05_organization.md#152-about-the-robot-framework-foundation) | K1 | List and recall the key objectives and organizational form of the [Robot Framework Foundation](./glossary#robot-framework-foundation) | | [`LO-1.5.3`](chapter-01/05_organization.md#153-robot-framework-webpages) | K1 | Recall the official webpages for Robot Framework and its resources | | [`LO-2.1`](chapter-02/01_suitefile.md) | K2 | Understand which files and directories are considered suites and how they are structured in a suite tree. | -| [`LO-2.1.1`](chapter-02/01_suitefile.md#211-suite-files) | K1 | Recall the conditions and requirements for a file to be considered a Suite file | +| [`LO-2.1.1`](chapter-02/01_suitefile.md#211-suite-files) | K1 | Recall the conditions and requirements for a file to be considered a [Suite](./glossary#suite) file | | [`LO-2.1.2`](chapter-02/01_suitefile.md#212-sections-and-their-artifacts) | K1 | Recall the available sections in a suite file and their purpose. | | [`LO-2.1.2.1-1`](chapter-02/01_suitefile.md#2121-introduction-to--settings--section) | K1 | Recall the available settings in a suite file. | | [`LO-2.1.2.1-2`](chapter-02/01_suitefile.md#2121-introduction-to--settings--section) | K2 | Understand the concepts of suite settings and how to define them. | @@ -31,7 +31,7 @@ | [`LO-2.2.3`](chapter-02/02_suitefile_syntax.md#223-in-line-comments) | K3 | Be able to add in-line comments to suites. | | [`LO-2.2.4`](chapter-02/02_suitefile_syntax.md#224-escaping-of-control-characters) | K2 | Understand how to escape control characters in Robot Framework. | | [`LO-2.2.5`](chapter-02/02_suitefile_syntax.md#225-example-suite-file) | K2 | Understand the structure of a basic suite file. | -| [`LO-2.3`](chapter-02/03_executing.md) | K1 | Recall the three components of the Robot Framework CLI. | +| [`LO-2.3`](chapter-02/03_executing.md) | K1 | Recall the three components of the [Robot Framework CLI](./glossary#command-line-interface). | | [`LO-2.3.1`](chapter-02/03_executing.md#231-robot-command--help) | K2 | Understand how to run the `robot` command and its basic usage. | | [`LO-2.3.2`](chapter-02/03_executing.md#232-execution-artifacts) | K2 | Explain the execution artifacts generated by Robot Framework. | | [`LO-2.3.3`](chapter-02/03_executing.md#233-status) | K1 | Recall the four different status labels used by Robot Framework. | @@ -50,7 +50,7 @@ | [`LO-2.5.2.2`](chapter-02/05_keyword_interface.md#2522-optional-arguments) | K2 | Understand the concept of optional arguments and how they are documented. | | [`LO-2.5.2.3`](chapter-02/05_keyword_interface.md#2523-embedded-arguments) | K1 | Recall the concept of keywords with embedded arguments used in Behavior-Driven Specification and how they are documented. | | [`LO-2.5.2.4`](chapter-02/05_keyword_interface.md#2524-positional-or-named-arguments) | K1 | Recall how "Positional or Named Arguments" are marked in the documentation and their use case. | -| [`LO-2.5.2.5`](chapter-02/05_keyword_interface.md#2525-variable-number-of-positional-arguments) | K1 | Recall how "Variable Number of Positional Arguments" are marked in the documentation and their use case. | +| [`LO-2.5.2.5`](chapter-02/05_keyword_interface.md#2525-variable-number-of-positional-arguments) | K1 | Recall how "[Variable Number of Positional Arguments](./glossary#variable-number-of-positional-arguments)" are marked in the documentation and their use case. | | [`LO-2.5.2.6`](chapter-02/05_keyword_interface.md#2526-named-only-arguments) | K1 | Recall what properties "Named-Only Arguments" have and how they are documented. | | [`LO-2.5.2.7`](chapter-02/05_keyword_interface.md#2527-free-named-arguments) | K1 | Recall how "Free Named Arguments" are marked in documentation. | | [`LO-2.5.2.8`](chapter-02/05_keyword_interface.md#2528-argument-types) | K2 | Understand the concept of argument types and automatic type conversion. | @@ -83,11 +83,11 @@ | [`LO-3.3.5.2-1`](chapter-03/03_user_keyword.md#3352-defining-optional-arguments) | K1 | Recall how to define optional arguments in a user keyword. | | [`LO-3.3.5.2-2`](chapter-03/03_user_keyword.md#3352-defining-optional-arguments) | K3 | Define User Keywords with optional arguments. | | [`LO-3.3.5.3-1`](chapter-03/03_user_keyword.md#3353-defining-embedded-arguments) | K2 | Describe how embedded arguments are replaced by actual values during keyword execution. | -| [`LO-3.3.5.3-2`](chapter-03/03_user_keyword.md#3353-defining-embedded-arguments) | K2 | Understand the role of embedded arguments in Behavior-Driven Development (BDD) style. | +| [`LO-3.3.5.3-2`](chapter-03/03_user_keyword.md#3353-defining-embedded-arguments) | K2 | Understand the role of embedded arguments in [Behavior-Driven Development](./glossary#behavior-driven-development) (BDD) style. | | [`LO-3.3.6-1`](chapter-03/03_user_keyword.md#336-return-statement) | K2 | Understand how the `RETURN` statement passes data between different keywords. | | [`LO-3.3.6-2`](chapter-03/03_user_keyword.md#336-return-statement) | K3 | Use the `RETURN` statement to return values from a user keyword and assign it to a variable. | | [`LO-3.3.7`](chapter-03/03_user_keyword.md#337-keyword-conventions) | K1 | Recall the naming conventions for user keywords. | -| [`LO-3.4`](chapter-03/04_datadriven.md) | K2 | Understand the basic concept and syntax of Data-Driven Specification | +| [`LO-3.4`](chapter-03/04_datadriven.md) | K2 | Understand the basic concept and syntax of [Data-Driven Specification](./glossary#data-driven-specification) | | [`LO-3.4.1-1`](chapter-03/04_datadriven.md#341-testtask-templates) | K2 | Understand how to define and use test\|task templates | | [`LO-3.4.1-2`](chapter-03/04_datadriven.md#341-testtask-templates) | K1 | Recall the differences between the two different approaches to define Data-Driven Specification | | [`LO-3.4.1.1`](chapter-03/04_datadriven.md#3411-multiple-named-testtask-with-one-template) | K1 | Recall the syntax and properties of multiple named test\|task with one template | @@ -98,20 +98,20 @@ | [`LO-3.5.3`](chapter-03/05_advanced_importing.md#353-naming-conflicts) | K2 | Explain how naming conflicts can happen and how to mitigate them. | | [`LO-4.1-1`](chapter-04/01_setups.md) | K1 | Recall the purpose and benefits of Setups in Robot Framework | | [`LO-4.1-2`](chapter-04/01_setups.md) | K1 | Recall the different levels where a Setup can be defined | -| [`LO-4.1.1-1`](chapter-04/01_setups.md#411-suite-setup) | K1 | Recall key characteristics, benefits, and syntax of Suite Setup | -| [`LO-4.1.1-2`](chapter-04/01_setups.md#411-suite-setup) | K2 | Understand when Suite Setup is executed and used | -| [`LO-4.1.2-1`](chapter-04/01_setups.md#412-testtask-setup) | K1 | Recall key characteristics, benefits, and syntax of Test Setup | -| [`LO-4.1.2-2`](chapter-04/01_setups.md#412-testtask-setup) | K2 | Understand when Test\|Task Setup is executed and used | -| [`LO-4.1.3`](chapter-04/01_setups.md#413-keyword-setup) | K1 | Recall key characteristics and syntax of Keyword Setup | +| [`LO-4.1.1-1`](chapter-04/01_setups.md#411-suite-setup) | K1 | Recall key characteristics, benefits, and syntax of [Suite Setup](./glossary#suite-setup) | +| [`LO-4.1.1-2`](chapter-04/01_setups.md#411-suite-setup) | K2 | Understand when [Suite Setup](./glossary#suite-setup) is executed and used | +| [`LO-4.1.2-1`](chapter-04/01_setups.md#412-testtask-setup) | K1 | Recall key characteristics, benefits, and syntax of [Test Setup](./glossary#test-setup) | +| [`LO-4.1.2-2`](chapter-04/01_setups.md#412-testtask-setup) | K2 | Understand when Test\|[Task](./glossary#task) Setup is executed and used | +| [`LO-4.1.3`](chapter-04/01_setups.md#413-keyword-setup) | K1 | Recall key characteristics and syntax of [Keyword](./glossary#keyword) Setup | | [`LO-4.2-1`](chapter-04/02_teardowns.md) | K2 | Understand the different levels where and how Teardowns can be defined and when they are executed | | [`LO-4.2-2`](chapter-04/02_teardowns.md) | K1 | Recall the typical use cases for using Teardowns | -| [`LO-4.2.1-1`](chapter-04/02_teardowns.md#421-suite-teardown) | K1 | Recall key characteristics, benefits, and syntax of Suite Teardown | -| [`LO-4.2.1-2`](chapter-04/02_teardowns.md#421-suite-teardown) | K2 | Understand when Suite Teardown is executed and used | -| [`LO-4.2.2-1`](chapter-04/02_teardowns.md#422-testtask-teardown) | K1 | Recall key characteristics, benefits, and syntax of Test\|Task Teardown | -| [`LO-4.2.2-2`](chapter-04/02_teardowns.md#422-testtask-teardown) | K2 | Understand when Test\|Task Teardown is executed and used | +| [`LO-4.2.1-1`](chapter-04/02_teardowns.md#421-suite-teardown) | K1 | Recall key characteristics, benefits, and syntax of [Suite Teardown](./glossary#suite-teardown) | +| [`LO-4.2.1-2`](chapter-04/02_teardowns.md#421-suite-teardown) | K2 | Understand when [Suite Teardown](./glossary#suite-teardown) is executed and used | +| [`LO-4.2.2-1`](chapter-04/02_teardowns.md#422-testtask-teardown) | K1 | Recall key characteristics, benefits, and syntax of Test\|[Task Teardown](./glossary#test-teardown) | +| [`LO-4.2.2-2`](chapter-04/02_teardowns.md#422-testtask-teardown) | K2 | Understand when Test\|[Task](./glossary#task) Teardown is executed and used | | [`LO-4.2.3`](chapter-04/02_teardowns.md#423-keyword-teardown) | K1 | Recall key characteristics, benefits, and syntax of Keyword Teardown | | [`LO-4.3`](chapter-04/03_init_files.md) | K1 | Recall how to define Initialization Files and its purpose | -| [`LO-4.3.2`](chapter-04/03_init_files.md#432-suite-setup-and-suite-teardown-of-initialization-files) | K2 | Understand the execution order of Suite Setup and Suite Teardown in Initialization Files and their sub-suites and tests\|tasks | +| [`LO-4.3.2`](chapter-04/03_init_files.md#432-suite-setup-and-suite-teardown-of-initialization-files) | K2 | Understand the execution order of [Suite](./glossary#suite) Setup and [Suite](./glossary#suite) Teardown in Initialization Files and their sub-suites and tests\|tasks | | [`LO-4.3.3`](chapter-04/03_init_files.md#433-allowed-sections-in-initialization-files) | K1 | Recall the allowed sections and their content in Initialization Files | | [`LO-4.4`](chapter-04/04_tags.md) | K1 | Recall the purpose of Test\|Task Tags in Robot Framework | | [`LO-4.4.1`](chapter-04/04_tags.md#441-assigning-tags-to-teststasks) | K1 | Recall the syntax and different ways to assign tags to tests\|tasks | @@ -136,3 +136,5 @@ | [`LO-5.2.4`](chapter-05/02_control_structures.md#524-for-loops) | K2 | Understand the purpose and basic concept of FOR Loops | | [`LO-5.2.5`](chapter-05/02_control_structures.md#525-while-loops) | K2 | Understand the purpose and basic concept of WHILE Loops | | [`LO-5.2.6`](chapter-05/02_control_structures.md#526-break-and-continue) | K2 | Understand the purpose and basic concept of the BREAK and CONTINUE statements | + + diff --git a/website/docs/overview.md b/website/docs/overview.md index 7f4df54..101cfd9 100644 --- a/website/docs/overview.md +++ b/website/docs/overview.md @@ -9,7 +9,7 @@ sidebar_position: 1 ## 0.1 About the Syllabus This syllabus serves as both a guidance document for participants and a requirement specification for Accredited Training Providers -preparing candidates for the "Robot Framework® Certified Professional" (RFCP®) exam. +preparing candidates for the "[Robot Framework® Certified Professional](./glossary#robot-framework-certified-professional)" ([RFCP](./glossary#robot-framework-certified-professional)®) exam. It outlines the structure, learning objectives, and knowledge areas essential for certification. This syllabus is not a training manual, tutorial, or comprehensive learning resource but instead defines the scope of knowledge @@ -34,7 +34,7 @@ but the specific teaching methods, order and pace may be adapted by the instruct ## 0.2 About "Robot Framework® Certified Professional" -The Robot Framework® Certified Professional (RFCP®) certification represents the foundational level of expertise in Robot Framework. It provides participants with a strong understanding of the core principles, syntax, and basic control structures needed to develop effective automation scripts. +The [Robot Framework® Certified Professional](./glossary#robot-framework-certified-professional) ([RFCP](./glossary#robot-framework-certified-professional)®) certification represents the foundational level of expertise in Robot Framework. It provides participants with a strong understanding of the core principles, syntax, and basic control structures needed to develop effective automation scripts. While the RFCP® includes an introduction to advanced features such as FOR-Loops and IF statements, the focus is primarily on awareness rather than in-depth mastery, @@ -87,10 +87,10 @@ Throughout this syllabus, participants will progress through these knowledge lev ## 0.5 About Accredited Training Providers -Accredited Training Providers are organizations officially accredited by the Robot Framework Foundation to offer certified training programs for a specific certification level. +Accredited Training Providers are organizations officially accredited by the [Robot Framework Foundation](./glossary#robot-framework-foundation) to offer certified training programs for a specific certification level. These partners shall deliver high-quality, structured courses designed to prepare candidates for the Robot Framework® Certified Professional (RFCP®) exam and other future Robot Framework certifications. -All training providers are members of the Robot Framework Foundation, +All training providers are members of the [Robot Framework Foundation](./glossary#robot-framework-foundation), and their training materials have been reviewed by independent Robot Framework experts chosen by the Robot Framework Foundation to ensure the Foundation's quality standards. Only these Accredited Training Providers are permitted to refer to their courses as "Robot Framework®" training or use the term "Robot Framework® Certified Professional" or "RFCP®" in connection with their programs, due to the trademark on these terms. @@ -144,4 +144,5 @@ Special recognition is given to **Gerwin Laagland**, **Simon Meggle**, and **Fra **Acknowledgment** -The creation of the "Robot Framework Certified Professional®" syllabus stands as a testament to the dedication and generosity of its contributors. Most of the work has been done pro bono, reflecting a deep commitment to the principles of open-source collaboration and knowledge sharing. Each contributor—from those who meticulously reviewed and refined the content to those who laid its very foundation—has left a lasting impact. Their combined efforts have ensured that this document serves as a meaningful and accessible resource. We extend our heartfelt gratitude to everyone involved for their invaluable contributions. \ No newline at end of file +The creation of the "Robot Framework Certified Professional®" syllabus stands as a testament to the dedication and generosity of its contributors. Most of the work has been done pro bono, reflecting a deep commitment to the principles of open-source collaboration and knowledge sharing. Each contributor—from those who meticulously reviewed and refined the content to those who laid its very foundation—has left a lasting impact. Their combined efforts have ensured that this document serves as a meaningful and accessible resource. We extend our heartfelt gratitude to everyone involved for their invaluable contributions. +