14. JSDoc
In N4JS, comments starting with two asterisks (in /** .. */
) are interpreted as
documentation comments. The format is similar to JavaDoc or Google
Closure annotations.
14.1. General N4JSDoc Features
We distinguish between line and inline tags. The format of the content of a tag is specific to the tag. Most line tags, however, contain a description which is simply multiline text with nested inline tags. Every comment may start with a description.
14.1.1. Provided Inline Tags
14.1.1.1. @code
Small code snippet, not validated yet.
14.1.1.2. @link
Link to a type of element, not validated or supported in navigation yet.
14.2. N4JSdoc for User Projects
14.2.1. Standard Tags
14.2.1.1. @author
Name of author, repeat for multiple authors. Name of author is not validated.
14.2.1.2. @param
Parameter description, not validated at the moment.
14.2.1.3. @return
Return description, not validated at the moment.
14.2.2. Test Related Tags
The following tags are supposed to be used only in tests.
14.2.2.1. @testee
Link to type (maybe a function) or member tested by the test.
Req. IDE-172: @testee Semantics (ver. 1)
-
Tag can be only used on either
-
methods annotated with
@Test
-
classes in test projects or folders, cf. @testeeFromType.
-
-
Tag requires a single argument, which is a fully qualified name to a type, including the module specifier. The format is as follows:
moduleSpecifier '.' typeName ( ('.'|'#') memberName)?
-
Tag is not repeatable, that is a single test method (or class) can refer to only one testee.
-
Tag precedes the
reqid
tag, i.e., if a@testee
is specified, thereqid
will be ignored.
The target element is to be fully qualified including the module specifier. The module specifier is simply the source folder relative path name with forward slashes. Type and element are added to that using dot as a separator. For example:
/**
* @testee some/package/Module.Type.member
*/
14.2.2.2. @testeeFromType
Instead of directly linking a test method to a testee, the testee is to be derived from the linked testee of the test class. This is useful if a base test class is defined with generic tests, e.g., for testing methods defined in an interface and implemented by some classes. This base test class is then extended by concrete test classes, correctly setting up the test fixture, e.g., creating instances of some classes implementing the interfaces tested in the base class.
In the following example, the is used. This tag will lead to a test documentation for B.foo
and C.foo
.
abstract class Base {
/**
* @testeeFromType
*/
@Test testFoo() {..}
}
/**
* @testee B.foo
*/
class TestB extends Base {}
/**
* @testee C.foo
*/
class TestC extends Base {}
The resulting spec has to be double-checked for consistency since it is easily possible that too many constraints are generated. |
14.2.2.3. @testeeType and @testeeMember
Specifying the testee at the test method directly should be sufficient
for most cases. The @testeeFromType
tag already provides support for some cases in which a base test class is reused by subtypes. This case usually only works if
the base test class tests a single method only. If the base test class
tests several methods and if a sub test class only provides a different
fixture, this mechanism is not sufficient. For that purpose, the two
tags @testeeFromType
and @@testeeMember
are to be used.
They enable the separation of a test related to a specific member and the concrete receiver type of the tested member.
The @testeeType
is to defined in the test class JSDoc (actually, it is not
recognized when defined in a member JSDoc). The @testeeMember
is specified in the test method JSDoc. The "real" testee is then computed from the testee type and the testee method.
1. This only works for instance members, so far! 2. There is no validation for invalid combinations! |
Assume the following testees:
class A {
foo(): void {..}
bar(): void { .. this.foo(); ..}
}
class B extends A {
@Override foo() { .. }
}
Assume that the tests have to ensure the same semantics for bar
, which is
maybe changed by a wrong implementation of foo
. That is, bar
is to be tested in
case of the receiver type A
and B
. This can be achieved by the following
tests:
/**
* @testeeType A.A
*/
class ATest {
fixture(): A { return new A(); }
/**
* @testeeMember bar
*/
@Test testBar(): void { assertBehavior( fixture().bar() ); }
}
/**
* @testeeType B.B
*/
class BTest extends ATest {
@Override fixture(): B { return new B(); }
}
This actually defines two tests, which is also recognized by the spec exporter:
-
testBar
for a receiver of typeA
:ATest
's JSDoc@testeeType
+ATest.testBar
's JSDoc@testeeMember
= testeeA.A.bar
-
testBar
for a receiver of typeB
:BTest
's JSDoc@testeeType
+ATest.testBar
's JSDoc@testeeMember
= testeeB.B.bar
In all cases when @testeeFromType or @testeeType /@testeeMember is used, the resulting spec has to be
double-checked for consistency. Consider if the multiplication of spec
constraints is truly required, in particular if the original semantics
of a method is not changed. Remember: It is possible to write API tests
and omit the spec constraint generation simply by not adding the testee
links.
|
Assume testees similar as in testeeType and testeeMethod. Since the semantics of bar
is not changed in B
, it is probably not necessary to generate the same constraint in the documentation for bar
twice (one in the section for class A
and another one in the section of class B
).
Still, we want the test to be executed for both receivers. This is how it is achieved:
abstract class BaseTest {
abstract fixture(): A;
/**
* @testeeMember bar
*/
@Test testBar(): void { assertBehavior( fixture().bar() ); }
}
/**
* @testeeType A.A
*/
class ATest extends BaseTest {
fixture(): A { return new A(); }
}
class BTest extends BaseTest {
@Override fixture(): B { return new B(); }
}
This actually defines two tests as in the previous example. Only one constraint is created in the spec by the spec exporter:
-
testBar
for a receiver of typeA
:
ATest
's JSDoc@testeeType
+BaseTest.testBar
's JSDoc@testeeMember
= testeeA.A.bar
Although a test for receiver of type B
is run, no additional constraint is
created since there is no @testeeType
available neither in BTest
nor in BaseTest
.
14.2.2.4. @reqid in Tests
ID of feature used in JSDoc
for the requirements section. If no
testee (via one of the tags above) is given, then the test is linked to
the requirement with given id.
14.3. N4JSDoc for API and Implementation Projects
The following tags are supposed to be used in API and implementation projects.
14.3.1. @apiNote
Simple note that is shown in the API compare view.
14.3.2. API Project Tags
The following tags are supposed to be used in API projects only.
14.3.2.1. @apiState
State of type or member definition, e.g., stable or draft. This can be used to define a history. In this case, the tag has to be repeated. For example:
/**
* @apiState stable (WK)
* @apiState reviewed (JvP)
*/