
Description
Use when writing or modifying tests inside MPS `@tests` models — `NodesTestCase` (typesystem, constraints, scopes, dataflow, generator output), `EditorTestCase` (intentions, actions, keystrokes, side-transforms, completion), `MigrationTestCase` (migration scripts), `BTestCase` (plain JUnit on hand-written Java/Kotlin runtime), inline annotations such as `has error` / `has type` / `ScopesTest`, label-based `node<label>` cross-references, caret markers, and running tests via MCP / in MPS. Reach for this skill whenever the task involves authoring or fixing tests in a `tests`-stereotype model, or interpreting failures from one.
SKILL.md
Writing Tests in MPS Models
MPS ships a dedicated test language — jetbrains.mps.lang.test — for testing language artefacts (typesystem, scopes, constraints, dataflow, editor, generator, migrations). Plain JUnit-style tests against runtime classes use jetbrains.mps.baseLanguage.unitTest (the BTestCase concept).
A test is a root node living in a model whose stereotype is tests (pass modelName: "<name>@tests" to mps_mcp_create_model; the on-disk file ends in @tests.mps). See aspect-model-stereotypes.md for all model identifiers. The test model lives in a Solution module carrying the tests facet, not in the language module itself, so it can depend on the language under test plus arbitrary runtime libraries.
This skill is the reference for what to put in a test model and what each test type means. For the mechanics of creating/modifying nodes via MCP, see mps-model-manipulation and the mps_mcp_* tool docs. Documentation: https://www.jetbrains.com/help/mps/testing-languages.html. Source: plugins/mps-testing/languages/lang.test/.
Critical Directives
- The test model must carry stereotype
tests(file name…@tests.mps). Without it, roots compile but are not discovered as JUnit tests. - Used languages on a test model:
jetbrains.mps.lang.test,jetbrains.mps.baseLanguage.unitTest, the language(s) under test, plusjetbrains.mps.baseLanguage,jetbrains.mps.baseLanguage.collections,jetbrains.mps.lang.smodel,jetbrains.mps.lang.textas needed by assertion code. - The containing Solution must carry the
testsfacet. Languages and Generators don't compile the test classes, so the test root must live in this dedicated Solution. Create it viamps_mcp_create_module(type="solution", …, facets="[\"tests\"]"); the response is self-describing —{"data":{"kind":"Solution","facets":["java","tests"],"loadExtensions":"NotAvailable",…}}confirms the kind without a follow-up call. For an existing Solution, attach the facet viamps_mcp_update_module_facet(facetType="tests", enabled=true)and verify withmps_mcp_get_project_structure(startingPoint="…")(itsfacetsarray will include"tests"). - The
testMethodsrole declaresNodesTestMethod, which is abstract — instantiateSimpleNodeTest(c:8585453e-6bfb-4d80-98de-b16074f1d86c/1225978065297). Inserting rawNodesTestMethodfails with"Abstract concept instance detected". - Inside snippets,
TestNodeAnnotationlabels are only resolvable viaTestNodeReferencefrom test-method bodies. For in-snippet references (e.g. settingRoutineCall.routine) use the target node's ownnameproperty (resolved through the language's scope) or a persistentr:node ref, never the label name. - Prefer
invoke action <ActionId>over rawpress <chord>for Enter/Tab/etc. inEditorTestCase—PressKeyStatementmay bypass the named-action dispatcher used by the production editor. Editor actions live inr:9832fb5f-2578-4b58-8014-a5de79da988e(jetbrains.mps.ide.editor.actions). - For an empty list role, target
empty_<role>for the caret — notrefNodeList_<role>(the latter is the populated wrapper cell). - Never edit
test_gen/orclasses_gen/— those are regenerated.
Common-Path Workflow
When asked to "write tests" for an MPS language feature:
- Decide the test type. Typesystem / scope / constraint →
NodesTestCase. Intention / action / keystroke →EditorTestCase. Migration →MigrationTestCase. Runtime helper →BTestCase. Generator output equivalence →NodesTestCase+assertNodesMatch. Seereferences/test-types.md. - Find or create the test model. Prefer extending an existing
@testsmodel in the language's adjacent test Solution; only create a new one if no suitable Solution exists. - Add the test root with
mps_mcp_create_root_nodeusing the concept ref fromreferences/concept-identifiers.md, then populatenodes/code/ etc. withmps_mcp_update_node. Usemps_mcp_parse_java_and_insertto drop a Java/BaseLanguage snippet into aTestNode. - Mark assertions using the appropriate annotation concept (see
references/nodes-test-case.mdandreferences/editor-test-case.md). For prototypes, open the model in MPS and use the Alt+Enter intentions ("Add Node Operations Test Annotation", "Add Test Node Label", "Mark Caret Position") — they create the right annotations without hand-building blueprints. - Validate with
mps_mcp_check_root_node_problemson the new root. - Run. Register a
JUnit Testsconfig viamps_mcp_create_run_configuration(pass the test root's reference) and launch it withexecute_run_configuration, or ask the user to run it in MPS.
Where Test Models Live
| Where | When |
|---|---|
Test aspect of the language (testAspect model under <lang>/) | Quick, language-local checks; cannot run in a fresh MPS instance from outside the language. |
Dedicated test Solution with @tests model | Recommended for anything serious. Runs out-of-process; can be wired into the build/CI. |
If the only goal is plain JUnit on hand-written Java/Kotlin (no MPS-specific assertions), prefer a regular module test source root rather than a @tests model — see mps-distribution-build for how BTestCase-based MPS test modules are packaged.
Related Skills
mps-model-manipulation— the smodel / closures / collections reference for assertion bodies.mps-node-editing— MCP recipes for inserting children and harvesting persistent refs (used heavily by theScopesTeststaged-construction recipe).mps-aspect-typesystem— when the system-under-test is the typesystem;has error/typeannotations here verify those rules.mps-aspect-constraints— when validatingcan-be/ scope / validator rules from the constraints aspect.mps-aspect-migrations— for migration scripts being exercised byMigrationTestCase.mps-aspect-intentionsandmps-aspect-editor-menus-and-keymaps— when anEditorTestCaseexercises intentions, side transforms, or keymapped actions.mps-build-languageandmps-distribution-build— when wiring a@testsSolution into the build pipeline (test-onlyBuildProject).mps-quotations— for tests that use quotation snippets.
Reference Index
- Open
references/test-model-setup.mdwhen bootstrapping a new@testsmodel — required stereotype, used languages, Solution kind, optionalTestInforoot, and the choice between the language'stestAspectand a dedicated test Solution. Includes the canonical example test Solutions in this repo. - Open
references/test-types.mdfor the test-type cheat sheet (concept refs and what each tests). Use to decide which root concept to instantiate. - Open
references/nodes-test-case.mdwhen authoring or modifying aNodesTestCase— section layout (nodes,test methods,utility methods,accessMode), inline assertion annotations (has error,has type,has typesystem error,has expected type,has type in), labelled-node assertions inside test methods, and the namespace separation between labels and scope-resolved references. - Open
references/scopes-test.mdwhen writing declarative scope assertions (ScopesTest+ScopesExpectedNode) — where to attach the annotation, the exact-set semantics, the JSON blueprint, the stage-construction recipe for resolving expected refs, and why declarative scope tests beat imperative ones. - Open
references/editor-test-case.mdwhen writing anEditorTestCase— root layout (before/result/code), theAnonymousCellAnnotationcaret marker, the cell-ID convention for auto-generated editors (property_<name>,refNodeList_<role>,empty_<role>,refNode_<role>, constant/collection cells), the editor-driving statements (type "...",press,invoke action,invoke intention,invoke quick-fix), the editor expressions usable insidecode(EditorComponentExpression→getEditorComponent(),IsIntentionApplicableExpression→isIntentionApplicable(),ProjectExpression→getProject(),ModelExpression→ model of the edited node), and the side-transform / completion testing pattern. - Open
references/generator-and-migration-tests.mdwhen validating generator output (NodesTestCase+assertNodesMatch) or testing a migration script (MigrationTestCase—inputNodes,outputNodes,migrationrefs,options includingStableIdOption). Lists the four-child structure ofMigrationTestCaseand the "Generate Output from Input" intention. - Open
references/btestcase.mdwhen writing plain JUnit-style tests against hand-written Java/Kotlin — theBTestCaseannotation,TestMethod/BeforeTest/AfterTest, and the available assertion concepts. - Open
references/running-tests.mdwhen launching tests — inside MPS (right-click → Run tests), from the command line via the Ant pipeline, or from an agent viamps_mcp_create_run_configuration+execute_run_configuration. Covers in-process vs separate-MPS-instance, andmps_mcp_check_root_node_problemsas a fast pre-run gate. - Open
references/common-failures.mdwhen a test won't run, runs but doesn't fail when expected, fails for the wrong reason, or generates a misleadingoutputNodes. Includes the abstract-concept gotcha, label-vs-name confusion,press VK_ENTERvsinvoke action Insert,replace_node_childref invalidation, andScopesExpectedNode.refnot being scope-resolved. - Open
references/concept-identifiers.mdfor the validated FQN+concept-ref table coveringjetbrains.mps.lang.test(every concept used by the skill —NodesTestCase,SimpleNodeTest,TestNode,TestNodeAnnotation,AnonymousCellAnnotation, the annotation/check operations, the editor-driving statements,ScopesTest/ScopesExpectedNode, etc.) andjetbrains.mps.baseLanguage.unitTest.
More skills from the MPS repository
View all 31 skillsmps-aspect-accessories
configure JetBrains MPS module dependencies
Jul 17ArchitectureConfigurationEngineeringmps-aspect-actions
define and edit MPS node factories
Jul 17ArchitectureEngineeringmps-aspect-behavior
define and edit MPS concept behavior
Jul 13ArchitectureEngineeringmps-aspect-constraints
define JetBrains MPS language constraints
Jul 17ArchitectureCode Analysismps-aspect-dataflow
define and debug MPS dataflow builders
Jul 13Data Analysismps-aspect-editor
define MPS editor layouts
Jul 13DesignUI Components
More from JetBrains
View publishermps-aspect-editor-menus-and-keymaps
author MPS editor menus and keymaps
MPS
Jul 13EngineeringUI Componentsmps-aspect-generation-plan
modify MPS generation plans
MPS
Jul 13ArchitectureEngineeringmps-aspect-generator
define JetBrains MPS generator rules
MPS
Jul 17ArchitectureCode AnalysisEngineeringmps-aspect-intentions
define and edit MPS intentions
MPS
Jul 17ArchitectureEngineeringmps-aspect-migrations
author and debug MPS migration scripts
MPS
Jul 13DebuggingMigrationmps-aspect-structure-concepts
define concepts in MPS structure aspect
MPS
Jul 17Data Modeling