Yes, macro-generated requires and provides are tricky. They key is the lexical scope of the require-spec (ie the (submod "." testmodule)
).
From the docs:
In require ... the generator of the require-spec determines the scope of the bindings.
In other words, the require-spec and the uses of required identifiers must have the same scope.
Here is a version of tinylang.rkt that will work:
#lang racket
(provide (all-defined-out))
(define-syntax (modularise stx)
(syntax-case stx ()
[(_ func)
(with-syntax ([require-spec (datum->syntax stx '(submod "." testmodule))])
#`(begin
(module testmodule racket
(provide working)
(define working func))
(require require-spec)))]))