Eindeutige Anforderungs-IDs und Liste der entsprechenden Testmethoden

Eindeutige Anforderungs-IDs und Liste der entsprechenden Testmethoden

Ich habe gelernt, wie man Anforderungen mit eindeutigen IDs erstelltin diesem Beitrag. Nun möchte ich für jede Anforderung eine Testmethode hinzufügen - im Code denke ich dabei an so etwas:

\Requirement{SOMEID}{This is the requirement text.}{This describes the testmethod.}

Später, in einem anderen Abschnitt, möchte ich diese Testmethoden durchlaufen, um sie aufzulisten. Am Ende suche ich nach so etwas wie:

Bildbeschreibung hier eingeben

Der erste Teil ist mir klar, aber wie kann man einen Parameter (die Testmethoden) „speichern“, um ihn später zu verwenden?

Antwort1

\csnameSie benötigen einen „assoziativen Speicher“, der mit oder mit bereits von bereitgestellten Datenstrukturen implementiert werden kann expl3.

Hier \Requirementwird die ID in einer Sequenz gespeichert, um sie zu indizieren, dann werden beide Texte in einer Eigenschaftenliste gespeichert. Das Speichern des Anforderungstexts wird hier nicht wirklich verwendet, aber Sie können sich entscheiden, ihn auf eine andere Weise zu verwenden, also ist es besser, ihn ebenfalls zu speichern.

Bei Bedarf kann die Sequenz so zugeordnet werden, dass alle zum Zeitpunkt der Definition gespeicherten Testmethoden bereitgestellt werden.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\Requirement}{mmm}
 {
  \subsubsection*{Requirement ~ ID ~ #1}
  #2
  \jfb_requirement_store:nnn { #1 } { #2 } { #3 }
 }
\NewDocumentCommand{\DescribeRequirements}{}
 {
  \seq_map_inline:Nn \g_jfb_requirement_ids_seq
   {
    \subsubsection*{##1} \prop_item:Nn \g_jfb_requirement_ids_prop { ##1@B } \par
   }
 }

\seq_new:N \g_jfb_requirement_ids_seq
\prop_new:N \g_jfb_requirement_ids_prop

\cs_new_protected:Nn \jfb_requirement_store:nnn
 {
  \seq_gput_right:Nn \g_jfb_requirement_ids_seq { #1 }
  \prop_gput:Nnx \g_jfb_requirement_ids_prop { #1@A } { \tl_trim_spaces:n { #2 } }
  \prop_gput:Nnx \g_jfb_requirement_ids_prop { #1@B } { \tl_trim_spaces:n { #3 } }
 }

\ExplSyntaxOff

\begin{document}

\section{Introduction}

Blah.

\section{Requirements}

\Requirement{SOMEID}{This is the requirement text.}{This describes the test method.}

\Requirement{SOMEOTHERID}{
  This is the other requirement text.
}{
  This describes the other test method.
}

\section{Test Methods}

\DescribeRequirements

\end{document}

Bildbeschreibung hier eingeben

Antwort2

Sie könnten hierfür \@starttocden - -Mechanismus von LaTeX verwenden .\addtocontents

Ich habe versucht, sicherzustellen, dass das folgende Beispiel sowohl mit als auch ohne kompiliert wirdHyperrefwird geladen.

Außerdem habe ich darauf geachtet, dass das \labelReferenzieren \refund Setzen von Lesezeichen klappt.

Möglicherweise müssen Sie das Beispiel mehrmals kompilieren, ohne Hilfsdateien zwischen den LaTeX-Läufen zu löschen, damit alles richtig übereinstimmt.

\documentclass{article}

\usepackage{hyperref}

\newcounter{TestMethod}
\newcounter{Requirement}

\makeatletter
\newcommand\listofrequirements{%
  \section{Requirements}%
  \IfFileExists{\jobname.lfr}{}{\par\noindent No requirements available.}%
  \@starttoc{lfr}%
}%
\newcommand\listoftestmethods{%
  \section{Testmethods}%
  \begin{description}%
  \def\makelabel##1{\hspace\labelsep\normalfont\bfseries##1}%
  \IfFileExists{\jobname.ltm}{}{\item[\textnormal{No test-methods available.}]\relax}%
  \@starttoc{ltm}%
  \end{description}%
}%
\newcommand\@multipleRequirements{}%
\AtEndDocument{\@multipleRequirements}%
\begingroup
\catcode`\/=14 %
\catcode`\%=12 /
\@firstofone{/
\endgroup
\newcommand\Requirement[3]{/
  \@bsphack
  {/
    \@ifundefined{Requirement@#1}{\global\@namedef{Requirement@#1}{DEFINED}}{/
      \gdef\@multipleRequirements{\@latex@warning@no@line{There were multiply-defined requirements}}/
      \@latex@warning{Requirement `#1' multiply defined}/
    }/
  }/
  \begingroup
  // Let's have \addtocontents / \protected@write write immediately:
  \let\writecopy\write
  \def\write{\immediate\writecopy}/
  // Prevent all of \protected@write's expansion (\edef-with \protect-mechanism-expansion and \write-expansion)
  // by nesting things either into two token-registers or into two \unexpanded.
  \toks@{\the\@temptokena}/
  \@temptokena\expandafter{\string\l@Requirement{%^^J{#1}%^^J{#2}%^^J}}/
  \addtocontents{lfr}{\the\toks@\relax}/
  \@temptokena\expandafter{\string\l@TestMethod{%^^J{#1}%^^J{#3}%^^J}}/
  \addtocontents{ltm}{\the\toks@\relax}/
  /\addtocontents{lfr}{\unexpanded{\unexpanded\expandafter{\string\l@Requirement{%^^J{#1}%^^J{#2}%^^J}}}\relax}/
  /\addtocontents{ltm}{\unexpanded{\unexpanded\expandafter{\string\l@TestMethod{%^^J{#1}%^^J{#3}%^^J}}}\relax}/
  \endgroup
  \@esphack
}/
}%
\newcommand\l@Requirement[1]{%
  %#1 =  {ID}{<requirement-text>}
  \PrintRequirement#1%
}%
\newcommand\l@TestMethod[1]{%
  %#1 = {ID}{<requirement-text>}
  \PrintTestMethod#1%
}%
\newcommand\PrintRequirement[2]{%
  %#1 = ID; #2 = <requirement-text>;
  \ifhmode\medskip\fi\par\noindent
  \begingroup
  \def\theRequirement{#1}%
  \refstepcounter{Requirement}%
  \def\@currentlabelname{#1}%
  \label{RequirementNamespace@Requirement #1}%
  \@ifundefined{Hy@raisedlink}{}{%
    \@tempcnta\Hy@currentbookmarklevel
    \Hy@StepCount\@tempcnta
    \expandafter\RequirementPassFirstToSecond\expandafter{\the\@tempcnta}%
    {\Hy@writebookmark{}{#1}{\@currentHref}}{toc}%
    \advance \@tempcnta by -1 %
    \xdef\Hy@currentbookmarklevel{\the \@tempcnta}%
    \@ifundefined{r@RequirementNamespace@TestMethod #1}{}{%
      \hyperref[{RequirementNamespace@TestMethod #1}]%
    }%
  }%
  {\textbf{Requirement~ID~{#1}}}%
  \\{#2}%
  \endgroup
}%
\newcommand\Requirement@MoveLabelData{}%
\newcommand\RequirementPassFirstToSecond[2]{#2{#1}}%
\newcommand\PrintTestMethod[2]{%
  %#1 = ID; #2 = <requirement-text>;
  \item[{%
    \def\theTestMethod{#1}%
    \refstepcounter{TestMethod}%
    \def\@currentlabelname{#1}%
    \expandafter\gdef\expandafter\Requirement@MoveLabelData\expandafter{%
      \romannumeral0%
      \expandafter\RequirementPassFirstToSecond\expandafter{\@currentlabel}{%
        \@ifundefined{Hy@raisedlink}{ }{%
          \expandafter\RequirementPassFirstToSecond\expandafter{\@currentlabelname}{%
            \expandafter\RequirementPassFirstToSecond\expandafter{\@currentHref}{ %<- This space must be!
              \def\@currentHref
            }%
            \def\@currentlabelname
          }%
        }%
        \def\@currentlabel
      }%
    }%
    \label{RequirementNamespace@TestMethod #1}%
    \@ifundefined{Hy@raisedlink}{}{%
      \@tempcnta\Hy@currentbookmarklevel
      \Hy@StepCount\@tempcnta
      \expandafter\RequirementPassFirstToSecond\expandafter{\the\@tempcnta}%
      {\Hy@writebookmark{}{#1}{\@currentHref}}{toc}%
      \advance\@tempcnta by -1 %
      \xdef\Hy@currentbookmarklevel{\the \@tempcnta}%
      \@ifundefined{r@RequirementNamespace@Requirement #1}{}{%
        \hyperref[{RequirementNamespace@Requirement #1}]%
      }%
    }%
    {#1:}%
  }]%
  \Requirement@MoveLabelData
  #2%
}%
\makeatother

\begin{document}

\section{This is just some section}

This is text in the section.

\noindent Reference to the requirement with ID ``SOMEOTHERID'': \ref{AA}.

\noindent Reference to the testing-method with ID ``SOMEOTHERID'': \ref{BB}.

\Requirement{SOMEID}{This is the requirement text.}{This describes the testmethod.}
\Requirement{SOMEOTHERID}{This \label{AA} is some different requirement text.}{This \label{BB} describes some different testmethod.}

\listofrequirements

\listoftestmethods

\end{document}

Falls die Zeilen in den Hilfsdateien zu lang werden, können Sie einige der Argumente nach dem Verbatim-Category-Code-Regime lesen und schreiben lassen. Wenn Sie das tun, kann das Makro \Requirementnicht innerhalb der Definitionen und/oder Argumente anderer Makros verwendet werden.

Zuerst konnte ich es nicht zum Laufen bringen mitxparse's v+-Argumenttyp, also habe ich mein eigenes Ding verwendet.

Ich konnte es nicht zum Laufen bringen mitxparse's v+-Argumenttyp aus folgendem Grund:xparseDer v+Argumenttyp von verwendet das ^^MZeichen = das ⟨Return⟩-Zeichen zur Bezeichnung von Zeilenenden. ( ^^M= ^^-Notation für das Zeichen, dessen Codepunkt 13 im internen Zeichenkodierungsschema der TeX-Engine ist – M ist der 13. Buchstabe im Alphabet; Codepunkt 13 des internen Zeichenkodierungsschemas der TeX-Engine bezeichnet wiederum das ⟨Return⟩-Zeichen.) Wenn also das v+Argument in die Datei geschrieben wird, muss der Integer-Parameter \newlinecharauch dieses Zeichen bezeichnen. Daher sollten Sie \protected@writezum Schreiben des v+Arguments in die Datei besser nicht verwenden, sondern etwas, das dies \writesofort tut, während die Änderung von \newlinecharnoch wirksam ist. Bei meinen ersten Versuchen mitxparseIch habe beim v+-Argument-Typ übersehen, dass das \writesofort erfolgen muss.

Hier kommt mein eigenes Ding, aber dahinter habe ich ein weiteres Beispiel hinzugefügt, mitxparseund sein v+-Argument-Typ zum Abrufen der verbalisierten Argumente:

\documentclass{article}

\usepackage{hyperref}

\newcounter{TestMethod}
\newcounter{Requirement}

\makeatletter

%%======================Code for \UDcollectverbarg=============================
%% \UDcollectverbarg{^^M-replacement}{<mandatory 1>}{<mandatory 2>}|<verbatim arg>|
%% 
%% reads <verbatim arg> under verbatim-catcode-regime and delivers:
%%
%%    <mandatory 1>{<mandatory 2>{<verbatim arg>}{|<verbatim arg>|}}
%%
%% Instead of verbatim-delimiter | the <verbatim arg> can be nested in braces.
%% You cannot use percent or spaces or horizontal tab as verbatim-delimiter.
%%
%% You can use <mandatory 1> for nesting calls to \UDcollectverbarg.
%% <mandatory 2> gets the <verbatim arg> twice: Once without verbatim-delimiters/braces,
%% once surrounded by verbatim-delimiters/braces.
%% Reason: When you feed it to \scantokens you don't need the verbatim-delimiters.
%%         When you use it for writing to temporary files and reading back,
%%         you need them.
%%=============================================================================
%% Check whether argument is empty:
%%=============================================================================
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%    
%% Due to \romannumeral0-expansion the result is delivered after two
%% expansion-steps/after two "hits" by \expandafter.
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
\long\def\UD@CheckWhetherNull#1{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
  {\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%%=============================================================================
\begingroup
\@makeother\^^M%
\@firstofone{%
  \endgroup%
  \newcommand\UDEndlreplace[2]{\romannumeral0\@UDEndlreplace{#2}#1^^M\relax{}}%
  \@ifdefinable\@UDEndlreplace{%
    \long\def\@UDEndlreplace#1#2^^M#3\relax#4#5{%
      \UD@CheckWhetherNull{#3}%
      { #5{#4#2}}{\@UDEndlreplace{#1}#3\relax{#4#2#1}{#5}}%
    }%
  }%
}%
\newcommand\UDcollectverbarg[3]{%
  \begingroup
  \let\do\@makeother % <- this and the next line switch to
  \dospecials        %    verbatim-category-code-régime.
  \catcode`\{=1      % <- give opening curly brace the usual catcode so a 
                     %    curly-brace-balanced argument can be gathered in
                     %    case of the first thing of the verbatimized-argument 
                     %    being a curly opening brace.
  \catcode`\ =10     % <- give space and horizontal tab the usual catcode so \UD@collectverbarg
  \catcode`\^^I=10   %    cannot catch a space or a horizontal tab as its 4th undelimited argument.
                     %    (Its 4th undelimited argument denotes the verbatim-
                     %     syntax-delimiter in case of not gathering a
                     %     curly-brace-nested argument.)
  \catcode`\%=14     % <- make percent comment.
  \kernel@ifnextchar\bgroup
  {% seems a curly-brace-nested argument is to be caught:
    \catcode`\}=2    % <- give closing curly brace the usual catcode also.
    \UD@collectverbarg{#1}{#2}{#3}{}%
  }{% seems an argument with verbatim-syntax-delimiter is to be caught:
    \do\{% <- give opening curly brace the verbatim-catcode again.
    \UD@collectverbarg{#1}{#2}{#3}%
  }%
}%
\newcommand\UD@collectverbarg[4]{%
  \do\ %   <- Now that \UD@collectverbarg has the delimiter or
  \do\^^I%    emptiness in its 4th arg, give space and horizontal tab
         %    the verbatim-catcode again.
  \do\^^M% <- Give the carriage-return-character the verbatim-catcode.
  \do\%%   <- Give the percent-character the verbatim-catcode.
  \long\def\@tempb##1#4{%
    \def\@tempb{##1}%
    \UD@CheckWhetherNull{#4}{%
      \def\@tempc{{##1}}%
    }{%
      \def\@tempc{#4##1#4}%
    }%
    \@onelevel@sanitize\@tempb % <- Turn characters into their "12/other"-pendants.
                               %    This may be important with things like the 
                               %    inputenc-package which may make characters 
                               %    active/which give them catcode 13(active).
    \expandafter\UDEndlreplace\expandafter{\@tempb}{#1}{\def\@tempb}% <- this starts 
                               %    the loop for replacing endline-characters.
    \@onelevel@sanitize\@tempc
    \expandafter\UDEndlreplace\expandafter{\@tempc}{#1}{\def\@tempc}%
    \expandafter\expandafter\expandafter\UD@@collectverbarg% <- this "spits out the result.
    \expandafter\expandafter\expandafter{%
    \expandafter\@tempb\expandafter}%
    \expandafter{\@tempc}{#2}{#3}%
  }%
  \@tempb
}%
\newcommand\UD@@collectverbarg[4]{%
  \endgroup
  #3{#4{#1}{#2}}%
}%
%%================= End of code for \UDcollectverbarg =========================

\newcommand\listofrequirements{%
  \section{Requirements}%
  \IfFileExists{\jobname.lfr}{}{\par\noindent No requirements available.}%
  \@starttoc{lfr}%
}%
\newcommand\listoftestmethods{%
  \section{Testmethods}%
  \begin{description}%
  \def\makelabel##1{\hspace\labelsep\normalfont\bfseries##1}%
  \IfFileExists{\jobname.ltm}{}{\item[\textnormal{No test-methods available.}]\relax}%
  \@starttoc{ltm}%
  \end{description}%
}%
\newcommand\@multipleRequirements{}%
\AtEndDocument{\@multipleRequirements}%
\newcommand\Requirement[1]{%
   \@bsphack
   \UDcollectverbarg{^^J}{%
     \UDcollectverbarg{^^J}{\@firstofone}%
   }{\InnerRequirement{#1}}%
}%
\newcommand\InnerRequirement[5]{%
  {%
    \@ifundefined{Requirement@#1}{\global\@namedef{Requirement@#1}{DEFINED}}{%
      \gdef\@multipleRequirements{\@latex@warning@no@line{There were multiply-defined requirements}}%
      \@latex@warning{Requirement `#1' multiply defined}%
    }%
  }%
  \begingroup
  \immediate\write\@auxout{\string\Requirementwritefile{lfr}{Requirement}{#1}#3}%
  \immediate\write\@auxout{\string\Requirementwritefile{ltm}{TestMethod}{#1}#5}%
  \endgroup
  \@esphack
}%
\newcommand\Requirementwritefile[3]{%
  \UDcollectverbarg{^^J}{\@firstofone}{%
    \expandafter\expandafter\expandafter\RequirementPassFirstToSecond
    \expandafter\expandafter\expandafter{\expandafter\string\csname l@#2\endcsname}%
    {\RequirementwritefileInner{#1}}{#3}%
  }%
}%
\begingroup
\catcode`\/=14 %
\@makeother{\%}/
\@firstofone{/
  \endgroup
  \newcommand\RequirementwritefileInner[5]{/
    \@writefile{#1}{/
      #2{%^^J/
      {#3}%^^J/
      {#4}%^^J/
      }%/
    }/
  }/
}%
\newcommand\l@Requirement[1]{%
  %#1 =  {ID}{<requirement-text>}
  \PrintRequirement#1%
}%
\newcommand\l@TestMethod[1]{%
  %#1 = {ID}{<requirement-text>}
  \PrintTestMethod#1%
}%
\newcommand\PrintRequirement[2]{%
  %#1 = ID; #2 = <requirement-text>;
  \ifhmode\medskip\fi\par\noindent
  \begingroup
  \def\theRequirement{#1}%
  \refstepcounter{Requirement}%
  \def\@currentlabelname{#1}%
  \label{RequirementNamespace@Requirement #1}%
  \@ifundefined{Hy@raisedlink}{}{%
    \@tempcnta\Hy@currentbookmarklevel
    \Hy@StepCount\@tempcnta
    \expandafter\RequirementPassFirstToSecond\expandafter{\the\@tempcnta}%
    {\Hy@writebookmark{}{#1}{\@currentHref}}{toc}%
    \advance\@tempcnta by -1 %
    \xdef\Hy@currentbookmarklevel{\the\@tempcnta}%
    \@ifundefined{r@RequirementNamespace@TestMethod #1}{}{%
      \hyperref[{RequirementNamespace@TestMethod #1}]%
    }%
  }%
  {\textbf{Requirement~ID~{#1}}}%
  \\{#2}%
  \endgroup
}%
\newcommand\Requirement@MoveLabelData{}%
\newcommand\RequirementPassFirstToSecond[2]{#2{#1}}%
\newcommand\PrintTestMethod[2]{%
  %#1 = ID; #2 = <requirement-text>;
  \item[{%
    \def\theTestMethod{#1}%
    \refstepcounter{TestMethod}%
    \def\@currentlabelname{#1}%
    \expandafter\gdef\expandafter\Requirement@MoveLabelData\expandafter{%
      \romannumeral0%
      \expandafter\RequirementPassFirstToSecond\expandafter{\@currentlabel}{%
        \@ifundefined{Hy@raisedlink}{ }{%
          \expandafter\RequirementPassFirstToSecond\expandafter{\@currentlabelname}{%
            \expandafter\RequirementPassFirstToSecond\expandafter{\@currentHref}{ %<- This space must be!
              \def\@currentHref
            }%
            \def\@currentlabelname
          }%
        }%
        \def\@currentlabel
      }%
    }%
    \label{RequirementNamespace@TestMethod #1}%
    \@ifundefined{Hy@raisedlink}{}{%
      \@tempcnta\Hy@currentbookmarklevel
      \Hy@StepCount\@tempcnta
      \expandafter\RequirementPassFirstToSecond\expandafter{\the\@tempcnta}%
      {\Hy@writebookmark{}{#1}{\@currentHref}}{toc}%
      \advance\@tempcnta by -1 %
      \xdef\Hy@currentbookmarklevel{\the\@tempcnta}%
      \@ifundefined{r@RequirementNamespace@Requirement #1}{}{%
        \hyperref[{RequirementNamespace@Requirement #1}]%
      }%
    }%
    {#1:}%
  }]%
  \Requirement@MoveLabelData
  #2%
}%
\makeatother

\begin{document}

\section{This is just some section}

This is text in the section.

\noindent Reference to the requirement with ID ``SOMEOTHERID'': \ref{AA}.

\noindent Reference to the testing-method with ID ``SOMEOTHERID'': \ref{BB}.

\Requirement{SOMEID}{This is the requirement text.}{This describes the testmethod.}
\Requirement{SOMEOTHERID}{This \label{AA} is some different requirement text.}{This \label{BB} describes some different testmethod.}

\listofrequirements

\listoftestmethods

\end{document}

Hier ist das Beispiel mit dem wörtlichen Argument unter Verwendungxparse‚s +v-Argument-Typ:

\documentclass{article}

\usepackage{xparse}
\usepackage{hyperref}

\newcounter{TestMethod}
\newcounter{Requirement}

\makeatletter
\NewDocumentCommand{\listofrequirements}{}{%
  \section{Requirements}%
  \IfFileExists{\jobname.lfr}{}{\par\noindent No requirements available.}%
  \@starttoc{lfr}%
}%
\NewDocumentCommand{\listoftestmethods}{}{%
  \section{Testmethods}%
  \begin{description}%
  \def\makelabel##1{\hspace\labelsep\normalfont\bfseries##1}%
  \IfFileExists{\jobname.ltm}{}{\item[\textnormal{No test-methods available.}]\relax}%
  \@starttoc{ltm}%
  \end{description}%
}%
\NewDocumentCommand{\@multipleRequirements}{}{}%
\AtEndDocument{\@multipleRequirements}%
\NewDocumentCommand{\Requirement}{m}{%
   \begingroup
   \@makeother{\^^I}%
   \InnerRequirement{#1}%
}%
\begingroup
\catcode`\/=14 %
\@makeother{\%}/
\@makeother{\^^M}/
\@firstofone{/
\endgroup/
\NewDocumentCommand{\InnerRequirement}{m+v+v}{/
  \endgroup/
  {/
    \@ifundefined{Requirement@#1}{\global\@namedef{Requirement@#1}{DEFINED}}{/
      \gdef\@multipleRequirements{\@latex@warning@no@line{There were multiply-defined requirements}}/
      \@latex@warning{Requirement `#1' multiply defined}/
    }/
  }/
  \begingroup/
  \newlinechar=\endlinechar/
  \immediate\write\@auxout{/
    \string\Requirementwritefile{lfr}/
                                {\unexpanded\expandafter{\string\l@Requirement{%^^M{#1}%^^M{#2}%^^M}}%}/
  }/
  \immediate\write\@auxout{/
    \string\Requirementwritefile{ltm}/
                                {\unexpanded\expandafter{\string\l@TestMethod{%^^M{#1}%^^M{#3}%^^M}}%}/
  }/
  \endgroup/
  \@esphack/
}/
}%
\NewDocumentCommand{\Requirementwritefile}{m}{%
  \begingroup
  \@makeother{\^^I}%
  \RequirementwritefileInner{#1}%
}%
\NewDocumentCommand{\RequirementwritefileInner}{m+v}{%
  \newlinechar=\endlinechar
  \@writefile{#1}{#2}%
  \endgroup
}%
\NewDocumentCommand{\l@Requirement}{+m}{%
  %#1 =  {ID}{<requirement-text>}
  \PrintRequirement#1%
}%
\NewDocumentCommand{\l@TestMethod}{+m}{%
  %#1 = {ID}{<requirement-text>}
  \PrintTestMethod#1%
}%
\NewDocumentCommand{\PrintRequirement}{+m+m}{%
  %#1 = ID; #2 = <requirement-text>;
  \ifhmode\medskip\fi\par\noindent
  \begingroup
  \def\theRequirement{#1}%
  \refstepcounter{Requirement}%
  \def\@currentlabelname{#1}%
  \label{RequirementNamespace@Requirement #1}%
  \@ifundefined{Hy@raisedlink}{}{%
    \@tempcnta\Hy@currentbookmarklevel
    \Hy@StepCount\@tempcnta
    \expandafter\RequirementPassFirstToSecond\expandafter{\the\@tempcnta}%
    {\Hy@writebookmark{}{#1}{\@currentHref}}{toc}%
    \advance\@tempcnta by -1 %
    \xdef\Hy@currentbookmarklevel{\the \@tempcnta}%
    \@ifundefined{r@RequirementNamespace@TestMethod #1}{}{%
      \hyperref[{RequirementNamespace@TestMethod #1}]%
    }%
  }%
  {\textbf{Requirement~ID~{#1}}}%
  \\{#2}%
  \endgroup
}%
\NewDocumentCommand{\Requirement@MoveLabelData}{}{}%
\NewDocumentCommand{\RequirementPassFirstToSecond}{+m+m}{#2{#1}}%
\NewDocumentCommand{\PrintTestMethod}{+m+m}{%
  %#1 = ID; #2 = <requirement-text>;
  \item[{%
    \def\theTestMethod{#1}%
    \refstepcounter{TestMethod}%
    \def\@currentlabelname{#1}%
    \expandafter\gdef\expandafter\Requirement@MoveLabelData\expandafter{%
      \romannumeral0%
      \expandafter\RequirementPassFirstToSecond\expandafter{\@currentlabel}{%
        \@ifundefined{Hy@raisedlink}{ }{%
          \expandafter\RequirementPassFirstToSecond\expandafter{\@currentlabelname}{%
            \expandafter\RequirementPassFirstToSecond\expandafter{\@currentHref}{ %<- This space must be!
              \def\@currentHref
            }%
            \def\@currentlabelname
          }%
        }%
        \def\@currentlabel
      }%
    }%
    \label{RequirementNamespace@TestMethod #1}%
    \@ifundefined{Hy@raisedlink}{}{%
      \@tempcnta\Hy@currentbookmarklevel
      \Hy@StepCount\@tempcnta
      \expandafter\RequirementPassFirstToSecond\expandafter{\the\@tempcnta}%
      {\Hy@writebookmark{}{#1}{\@currentHref}}{toc}%
      \advance \@tempcnta by -1 %
      \xdef\Hy@currentbookmarklevel{\the \@tempcnta}%
      \@ifundefined{r@RequirementNamespace@Requirement #1}{}{%
        \hyperref[{RequirementNamespace@Requirement #1}]%
      }%
    }%
    {#1:}%
  }]%
  \Requirement@MoveLabelData
  #2%
}%
\makeatother

\begin{document}

\section{This is just some section}

This is text in the section.

\noindent Reference to the requirement with ID ``SOMEOTHERID'': \ref{AA}.

\noindent Reference to the testing-method with ID ``SOMEOTHERID'': \ref{BB}.

\Requirement{SOMEID}{This is the requirement text.}{This describes the testmethod.}
\Requirement{SOMEOTHERID}{This \label{AA} is some different requirement text.}{This \label{BB} describes some different testmethod.}

\listofrequirements

\listoftestmethods

\end{document}

Bildbeschreibung hier eingeben

verwandte Informationen