Splitting macros to individual tokens/characters, with catcode (to debug conditionals)?

The command \tl_analysis_show:N does what you ask for.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\checktokenbytoken}{sm}
 {
  \IfBooleanTF{#1}
   {
    \tl_show_analysis:n { #2 }
   }
   {
    \tl_show_analysis:N #2
   }
 }
\ExplSyntaxOff

\edef\xgerman{\string german\relax}

\checktokenbytoken{\xgerman}
\checktokenbytoken*{german\relax}

You'll get, on the terminal,

The token list \xgerman contains the tokens:
>  g (the character g)
>  e (the letter e)
>  r (the letter r)
>  m (the letter m)
>  a (the letter a)
>  n (the letter n)
>  \relax (control sequence=\relax).
<recently read> }

l.19 \checktokenbytoken{\xgerman}

? 
The token list contains the tokens:
>  g (the letter g)
>  e (the letter e)
>  r (the letter r)
>  m (the letter m)
>  a (the letter a)
>  n (the letter n)
>  \relax (control sequence=\relax).
<recently read> }

l.20 \checktokenbytoken*{german\relax}

(For releases before TeX Live 2017, you will need \usepackage{l3tl-analysis} in addition to \usepackage{xparse} for this to work and \tl_show_analysis:N, now deprecated)


My solution doesn't need any external package. The \showcat\macro is implemented. After

\def\test{ger{$##m}a~n \relax \foo}
\edef\curentry{\string german \relax}

\showcat\test
\showcat\curentry

we get the result:

\test -> 
  the letter g (catcode 11)   
  the letter e (catcode 11)
  the letter r (catcode 11)
  begin-group character { (catcode 1)
  math shift character $ (catcode 3)
  macro parameter character # (catcode 6)
  the letter m (catcode 11)
  end-group character } (catcode 2)
  the letter a (catcode 11)
  the token ~ (catcode 13)
  the letter n (catcode 11)
  blank space   (catcode 10)
  the token \relax (catcode 16)
  the token \foo (catcode 16)
\curentry -> 
  the character g (catcode 12)
  the letter e (catcode 11)
  the letter r (catcode 11)
  the letter m (catcode 11)
  the letter a (catcode 11)
  the letter n (catcode 11)
  blank space   (catcode 10)
  the token \relax (catcode 16)

And the implementation:

\def\showcat#1{\immediate\write16{\string#1 -> }\expandafter\showcatA#1\showcatA}
\def\showcatA{\futurelet\tmp\showcatB}
\def\showcatB{\let\next=\showcatE
   \ifx\tmp\bgroup \let\next=\showcatC \fi
   \ifx\tmp\egroup \let\next=\showcatC \fi
   \expandafter\ifx\space\tmp \let\next=\showcatC \fi
   \ifx\tmp\showcatA \let\next=\showcatF \fi
   \next
}
\def\showcatC{\afterassignment\showcatD \let\tmp= }
\def\showcatD{\showcatE\tmp}

\def\showcatE#1{\edef\next{\string#1}%
   \immediate\write16{\space\space 
       \ifnum\showcatG<13 \meaningtmp \else the token \next
       \fi \space (catcode \showcatG)}%
   \showcatA
}
\def\meaningtmp{\meaning\tmp}
\def\showcatF#1{}
\def\showcatG{\showcatH\bgroup1\showcatH\egroup2\showcatH$3\showcatH&4%
   \showcatH##6\showcatH^7\showcatH_8\showcatH{ }{10}%
   \showcatH A{11}\showcatH/{12}\showcatH~{13}16}
\def\showcatH#1#2{\ifcat\noexpand\tmp\noexpand#1#2\expandafter\showcatI\fi}
\def\showcatI#116{}

Of course, the tokens with category 0, 5, 9, 14, 15 never occur in the macro body. And the control sequences (tokens without category) are expressed here as category 16 in order to simple usage of \showcatG in \ifnum tests.