The reality, then, is that we don't publish things, but publish things as of certain times. Only by putting the concept of publication time in the interface do we communicate the true semantics of publication.
To look at it another way, if you call the publish! method without understanding how publication time affects the thing you're publishing, aren't you missing something important?
So, to make the semantics of publication clear, the publish! method ought to have a publication-time parameter of some sort. (But it shouldn't be called current_time, as that name doesn't reflect the actual semantics of publication. We don't want to suggest, for example, that it requires time travel to schedule things for future publication.)
I agree with everything else you've said around the semantics of publishing something, but those are implementation details of the application at hand. Having a #publish_at!(publish_time) method may or may not be what users need in this application, but the original example (adding a parameter to make testing cleaner) seems like a clear case of writing to the test to me.
So, yes, if the original author left the concept of publication time out of the publish! method, that was probably a mistake. Likewise, adding a current_time parameter to that interface for the purpose of injection at testing time was also a mistake.
But my point is that both of these mistakes are downstream consequences of failing to recognize that, in this application, the published_at time is an essential part of the publication semantics and ought to be clearly expressed in the interface for publishing things. Had it been been expressed, there would have been no problem during testing because the interface would already work for any given publish_at time and not be hard-coded for the single (although common) case of publishing at now.
In sum, a better interface all around would have been to have the publish! method take a publish_at time that defaults to the current time. You can't really make the interface "simpler" by leaving it out of the method interface: it's essential to publishing something, so it must be there somewhere, if not spelled out clearly in the interface, then hard-coded to some value internally, where all it can do is cause trouble.
Is the ability to future-date something problematic? The apps I've done that in it's called a feature.
You could always write a test for it though.
def publish!(current_time_TEST_USE_ONLY = Time::now)
self.update published_at: current_time_TEST_USE_ONLY
end
Another way to do it (what I do) is simply run the test, and compare obj.published_at to Time::now. If they differ by more than 100ms, something has gone terribly wrong (if you use Ruby, maybe replace 100ms with 1s).Please don't do this. It'll work fine for you, but if your tests ever get integrated into a larger system, then tests may start breaking randomly. I might be running tests concurrently, for example. On a virtual machine whose host is a bit more heavily loaded than normal. Running a large test suite is one situation where I don't care about interactivity and can just go away and come back later. Except that with a test that makes assumptions about running time, I can't. And this problem has actually happened to me, so isn't just hypothetical.
Why is this a problem?