If you add \tracingmacros=1 just before the use of \pattest you'll see in the log file what actually happens. Mine shows the following:
\pattest #1->\ucletter \p@tcnom
#1<-void
\ucletter ->\expandafter \makeupcase
\p@tcnom ->\ifmale der Patient\else die Patientin\fi
\makeupcase #1->\uppercase {#1}
#1<-\ifmale
...
This means that \makeupcase is applied to the \ifmale token and not to the expanded string. So another expansion is necessary, for which \expandafter before \ucletter would help.
Another issue is with the braces. When you replace the \pattest definition by \def\pattest#1{\expandafter\ucletter\p@tcnom} you'll get the following (againg in the log):
\pattest #1->\expandafter \ucletter \p@tcnom
#1<-void
\p@tcnom ->\ifmale {der Patient}\else {die Patientin}\fi
\ucletter ->\expandafter \makeupcase
\makeupcase #1->\uppercase {#1}
#1<-die Patientin
...
So the braces group the letters and make the whole word an argument to \makeupcase. That's why all the letters switch case. You'll have to remove the braces.
Also, I don't really understand why do you define \pattest with an argument which is thrown away then, but it's irrelevant for the problem here.
The following code is a minimal modification of your MWE which produces the correct output with only the first letter is uppercased:
\documentclass{article}
\def\ucletter{\expandafter\makeupcase}
\def\makeupcase#1{\uppercase{#1}}
\newif\ifmale
\makeatletter
\def\p@tctst{die Patientin}
\def\p@tcnom{\ifmale der Patient\else die Patientin\fi}
\def\mytesti#1{\ucletter\p@tctst}
\def\pattest#1{\expandafter\ucletter\p@tcnom}
\makeatother
\begin{document}
\mytesti{void} ist nicht \pattest{void}.
\end{document}
\def\p@tcnom{\ifmale der Patient\else die Patientin\fi}(without braces inside the definition) and\def\pattest#1{\expandafter\ucletter\p@tcnom}(instead of\edefin the first definition). – Sergei Golovan Nov 28 '17 at 07:41