This is basically a confusion about what macros do and when they run, and what they are supposed to return.
The problem is that your string macro body executes when shortly after the code is parsed (technically, when the code is “lowered”), which happens before your @testset code runs. So, the line xx["a"] = "apple" hasn’t executed yet, and the dictionary lookup fails.
A solution is to change your macro definition to return an expression that constructs the desired string, so that it doesn’t actually execute the xx[suf] lookup when the macro is lowered (when the macro body runs), but only when the corresponding line is executed:
macro x_str(str,suf)
return :($str * $xx[$suf])
end