Re: How do you write tests if you aren't sure what the result should be?
Avi Kessner <[email protected]>
| Newsgroups | gmane.comp.programming.test-driven-development |
|---|---|
| Message-ID | <CAGEhWpHXgh6bgZhzWDBNi2CPhM-y+ARjk7ztgpmMuwPNqXEibg@mail.gmail.com> |
Ron, very impressive, thank you. Part of what was tricking me, is the fact that I don't know that I want the penguin to go 900 pixels in 2 seconds. I want the penguin to go as far as it can, for as long as it can. (or in my particular boring usecase, as far as it can in 2 seconds) However with the concept of "render+, simuluate-" I think it can be abstracted out enough, and using what you did, the process will become more clear. I'm very thankful. Meaning, I can test that the number of simulations that happen for any given dt is constant regardless of the actual dt in calling the render function. brought to you by the letters A, V, and I and the number 47 On Sun, Feb 17, 2013 at 1:39 PM, Ron Jeffries <[email protected]> wrote: > Hi Avi … > > On Feb 17, 2013, at 1:03 AM, Avi Kessner <[email protected]> wrote: > >> My comparison was supposed to be regarding the culmative calculation, not >> the per tick calculation. >> >> Ill have to look up when velocity is multiplied vs when it's added. > > > I was supposing that dt is some kind of a time value. I imagined that it meant "delta time" or "change in time since last time". Its dimensions must surely be "seconds" or some other time value. I don't know whether you have set > > I was supposing that x is some kind of position value. I imagined that its dimensions were "meters" or "pixels", or some other distance value. > > The expression was x += dt. Dimensionally, pixels += seconds, or meters += seconds. Can't really be right. > > Now what we often do when we animate a penguin -- I mean who doesn't animate a penguin every now and again -- is reason as follows: > > I suppose I'll get about 30 frames a second; > I suppose I'd like him to move across the screen in about 2 seconds; > The way gravity works is you go constant speed in X but up and down in Y; > I plan to get 30 frames a second; > So I'll need 60 frames to move him > The part of the screen he'll move across is about 900 pixels; > He has to move 900/60 … uh … 15 pixels every second in the x direction; > … and so on > > Then, having done the math, when we calculate the penguin's x in our draw() code, called, we guess, every 1/30 second, we can just write: > > x += 15 > > Then the new iPad comes out and our draw() function is called 60 times a second and poor Pengi zips across so fast that it's no fun. So we reason: > > OK, well, he's moving 15 per tick. But now on the new iPad I get 60 ticks and he should move about half that. > I should generalize this. > Hm, well, I want him to go 900 pixels in 2 seconds. That's 450 pixels per second. > Um, maybe if I just read out the actual time since last time I can use that. > So I'll save time in timeThen and read time now and difference them. > the time() function is a float, seconds since long time ago. > > And we write > > draw() > timeNow = time() > dt = timeNow - timeThen > x += 450*dt > timeThen = timeNow > end > > Now our draw() function is independent of frame rate. But wait! what is that 450*dt??? It seems we just added time to distance and that's supposed to be wrong. It's ok. look at the dimensional analysis of that statement: > > pixels += (pixels/second)*second > > the seconds cancel and we're adding pixels to pixels > if x was in meters, it'd be meters += (meters/second)*second, so that would be OK too. > > Now our question here is how to TDD all this. I would do at least this much thinking with pencil and paper, which takes less time than it took to write this. To TDD the patch of code above, I've got a problem, which is that it calls time(). I can't really TDD well that way, because time is always weird. Just as we do with a random number, we need to abstract time out, so that our test can look like this: > > deltaTime = 1.0/30.0 > assertEquals(15, distanceMoved(deltaTime)) > > This requires us to write > > distanceMoved(float dt) > return 450*dt > end > > which means our draw function needs to be > > draw() > timeNow = time() > dt = timeNow-timeThen > x += distanceMoved(dt) > timeThen = timeNow > end > > Now how might we TDD that whole patch. Honestly unless I was demonstrating my great TDD powers, I'm not sure I would, but your mission is to demonstrate great TDD powers. It's darned hard to do in retrospect, when the code is so easy, but we have to learn to think backwards, so let's pretend that we are thinking that the draw has to look like that but that we were being really retentive about TDD, and didn't type it in yet. So we reason, knowing full well what we want: > > OK, we have a way to compute distanceMoved as a function of a delta-time. > Now we need a way to measure delta time. > So, um, let's have a delta-time function that we call in our draw. Its test is, um … > > beginTime = 1.5 > initDeltaTime(beginTime) > endTime = 2 > assertEquals(0.5, deltaTime(endTime)) > endTime = 3.5 > assertEquals(1.5, deltaTime(endTime)) > > Hmm, how can we write delta time? Well … > > lastTime = 0.0 > initDeltaTime(float aTime) > lastTime = aTime > end > > float deltaTime(float aTime) > dt = aTime-lastTime > lastTime = atime > return dt > end > > Now the draw() that we have in our head looks like > x += distanceMoved(deltaTime(time()) > y += godWhatWillWeDoAboutY(time()) > sprite("penguin", x, y) > > and both the distanceMoved function and the deltaTime function have been fully TDD'd. Now we do the y function. > Because we've read that article that you posted, we realize that we want a velocity that isn't constant 450/second, but is instead a function of gravity. And we know that we want to do that average velocity trick -- after we understand it, which we might not at the beginning. > > We proceed similarly. Your mission, if you care to, is to follow my reasoning above, then try to reason similarly as you calculate Y. I don't know yet what I'd do, because I'm stopping here for now. Unless I decide to animate a penguin in Codea … > > Hang in there! > > Ron Jeffries > www.XProgramming.com > It's true hard work never killed anybody, but I figure, why take the chance? > -- Ronald Reagan > > > > > > [Non-text portions of this message have been removed] > > > > ------------------------------------ > > Yahoo! Groups Links > > > ------------------------------------ Yahoo! Groups Links <*> To visit your group on the web, go to: http://groups.yahoo.com/group/testdrivendevelopment/ <*> Your email settings: Individual Email | Traditional <*> To change settings online go to: http://groups.yahoo.com/group/testdrivendevelopment/join (Yahoo! ID required) <*> To change settings via email: [email protected] [email protected] <*> To unsubscribe from this group, send an email to: [email protected] <*> Your use of Yahoo! Groups is subject to: http://docs.yahoo.com/info/terms/