Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #54924 > unrolled thread

Python Unit Tests

Started bymelwin9@gmail.com
First post2013-09-27 21:52 -0700
Last post2013-09-30 20:06 -0400
Articles 11 — 5 participants

Back to article view | Back to comp.lang.python


Contents

  Python Unit Tests melwin9@gmail.com - 2013-09-27 21:52 -0700
    Re: Python Unit Tests Dave Angel <davea@davea.name> - 2013-09-28 06:11 +0000
    Re: Python Unit Tests Terry Reedy <tjreedy@udel.edu> - 2013-09-28 14:47 -0400
      Re: Python Unit Tests melwin9@gmail.com - 2013-09-29 18:46 -0700
        Re: Python Unit Tests Steven D'Aprano <steve@pearwood.info> - 2013-09-30 02:55 +0000
          Re: Python Unit Tests melwin9@gmail.com - 2013-09-29 21:19 -0700
            Re: Python Unit Tests Terry Reedy <tjreedy@udel.edu> - 2013-09-30 02:08 -0400
    Re: Python Unit Tests melwin9@gmail.com - 2013-09-30 12:54 -0700
      Re: Python Unit Tests MRAB <python@mrabarnett.plus.com> - 2013-09-30 21:08 +0100
      Re: Python Unit Tests Dave Angel <davea@davea.name> - 2013-09-30 20:20 +0000
      Re: Python Unit Tests Terry Reedy <tjreedy@udel.edu> - 2013-09-30 20:06 -0400

#54924 — Python Unit Tests

Frommelwin9@gmail.com
Date2013-09-27 21:52 -0700
SubjectPython Unit Tests
Message-ID<bb6482de-ce4e-4dd2-845c-f71008123c03@googlegroups.com>
Hey,

How do i go about coming up/coding tests for this program below. Not sure how to even approach writing about 5 tests for it.

Initially I had this for the test but its not working well.

Test was name test_guess.py (Code Below)

[code]
from unittest import TestCase 
import pexpect as pe 

import guess as g 
import random 

random_number = random.randrange(1, 10) 
correct = False 

class GuessTest(TestCase): 
    def setUp(self): 
        self.intro = 'I have chosen a number from 1-10' 
        self.request = 'Guess a number: ' 
        self.responseHigh = "That's too high." 
        self.responseLow  = "That's too low." 
        self.responseCorrect = "That's right!" 
        self.goodbye = 'Goodbye and thanks for playing!' 
        
    def test_main(self): 
        #cannot execute main now because it will 
        #require user input 
        from guess import main 
        
    def test_guessing_hi_low_4(self): 
        # Conversation assuming number is 4 
        child = pe.spawn('python guess.py') 
        child.expect(self.intro,timeout=5) 
        child.expect(self.request,timeout=5) 
        child.sendline('5') 
        child.expect(self.responseHigh,timeout=5) 
        child.sendline('3') 
        child.expect(self.responseLow,timeout=5) 
        child.sendline('4') 
        child.expect(self.responseCorrect,timeout=5) 
        child.expect(self.goodbye,timeout=5) 


    def __init__(self): 
        self.number = random.randint(0,10) 
        HIGH = 1 
        LOW = 2 
        OK = 3 

    def guess(self, number): 
        if number > self.number: 
         return self.HIGH 
        if number < self.number: 
         return self.LOW 
        return self.OK 

    def test_guesstoolow(self): 
        while not correct: 
            guess = input("What could it be?") 
            if guess == random_number: 
                print "Congrats You Got It" 
                correct = True 
            elif guess > random_number: 
                print "To High" 
            elif guess < random_number: 
                print "To Low" 
            else: 
                print "Try Again"  [/code]

Python code for game below

[code]
import random

intro = 'I have chosen a number from 1-10'
request = 'Guess a number: '
responseHigh = "That's too high."
responseLow  = "That's too low."
responseCorrect = "That's right!"
goodbye = 'Goodbye and thanks for playing!'

print(intro)

def main():
    guessesTaken = 0
    number = random.randint(1, 10)
    while guessesTaken < 5:
        print(request)
        guess = input()
        guess = int(guess)

        guessesTaken = guessesTaken + 1

        if guess < number:
            print(responseLow) 

        if guess > number:
            print(responseHigh)

        if guess == number:
            break

    if guess == number:
            guessesTaken = str(guessesTaken)
            print(responseCorrect + '! You guessed my number in ' + guessesTaken + ' guesses!')

    if guess != number:
        number = str(number)
        print(goodbye + ' The number I was thinking of was ' + number)

##def main():
#    print(intro)
 #   user_input = raw_input(request)
  #  print(responseHigh)
  #  print(request)
  #  user_input = raw_input(request)
  #  print(responseLow)
  #  user_input = raw_input(request)
  #  print(responseCorrect)
  #  print(goodbye)

if __name__ == '__main__':
    main()[/code]

[toc] | [next] | [standalone]


#54929

FromDave Angel <davea@davea.name>
Date2013-09-28 06:11 +0000
Message-ID<mailman.403.1380348739.18130.python-list@python.org>
In reply to#54924
On 28/9/2013 00:52, melwin9@gmail.com wrote:

> Hey,
>

What version of Python are you using?  I'll assume 2.7, but you really
should specify it (and any other meaningful environment dependencies) in
your original query, the beginning of your thread.

For 2.7, the docs for unittest are at:

http://docs.python.org/2/library/unittest.html

> How do i go about coming up/coding tests for this program below. Not sure how to even approach writing about 5 tests for it.
>
> Initially I had this for the test but its not working well.
>
> Test was name test_guess.py (Code Below)
>
> [code]
> from unittest import TestCase 
> import pexpect as pe 
>
> import guess as g 
> import random 
>
> random_number = random.randrange(1, 10) 
> correct = False 
>
> class GuessTest(TestCase): 
>     def setUp(self): 
>         self.intro = 'I have chosen a number from 1-10' 
>         self.request = 'Guess a number: ' 
>         self.responseHigh = "That's too high." 
>         self.responseLow  = "That's too low." 
>         self.responseCorrect = "That's right!" 
>         self.goodbye = 'Goodbye and thanks for playing!' 

These strings don't change from one test to another.  Thus they could be
set in the __init__() method, and indeed could just be globals.  Or even
(horrors) imported from the guess module.  So in your tests, you might
refer to  g.intro, rather than self.intro   Or you might decide that the
content of the strings is not what you're testing, but rather the flow
of the logic.


>         
>     def test_main(self): 
>         #cannot execute main now because it will 
>         #require user input 
>         from guess import main 

No need for an import here.  Assuming you will be adding a call to
main(), you can just call it as  g.main(), since you imported g already
as a global.

>         
>     def test_guessing_hi_low_4(self): 
>         # Conversation assuming number is 4 
>         child = pe.spawn('python guess.py') 
>         child.expect(self.intro,timeout=5) 
>         child.expect(self.request,timeout=5) 
>         child.sendline('5') 
>         child.expect(self.responseHigh,timeout=5) 
>         child.sendline('3') 
>         child.expect(self.responseLow,timeout=5) 
>         child.sendline('4') 
>         child.expect(self.responseCorrect,timeout=5) 
>         child.expect(self.goodbye,timeout=5) 
>
>
>     def __init__(self): 
>         self.number = random.randint(0,10) 
>         HIGH = 1 
>         LOW = 2 
>         OK = 3 

Those 3 statements do nothing useful.  They set 3 local variables which
are then immediately forgotten.  Presumably you meant:

       self.HIGH = 1
       self.LOW = 2
       self.OK = 3

>
>     def guess(self, number): 
>         if number > self.number: 
>          return self.HIGH 
>         if number < self.number: 
>          return self.LOW 
>         return self.OK 
>
>     def test_guesstoolow(self): 

Nothing in this method tests any of the actual program

>         while not correct: 
>             guess = input("What could it be?") 
>             if guess == random_number: 
>                 print "Congrats You Got It" 
>                 correct = True 
>             elif guess > random_number: 
>                 print "To High" 
>             elif guess < random_number: 
>                 print "To Low" 
>             else: 
>                 print "Try Again"  [/code]
>
> Python code for game below
>
> [code]
> import random
>
> intro = 'I have chosen a number from 1-10'
> request = 'Guess a number: '
> responseHigh = "That's too high."
> responseLow  = "That's too low."
> responseCorrect = "That's right!"
> goodbye = 'Goodbye and thanks for playing!'
>
> print(intro)
>
> def main():
>     guessesTaken = 0
>     number = random.randint(1, 10)
>     while guessesTaken < 5:
>         print(request)
>         guess = input()
>         guess = int(guess)
>
>         guessesTaken = guessesTaken + 1
>
>         if guess < number:
>             print(responseLow) 
>
>         if guess > number:
>             print(responseHigh)
>
>         if guess == number:
>             break
>
>     if guess == number:
>             guessesTaken = str(guessesTaken)
>             print(responseCorrect + '! You guessed my number in ' + guessesTaken + ' guesses!')
>
>     if guess != number:
>         number = str(number)
>         print(goodbye + ' The number I was thinking of was ' + number)
>
> ##def main():
> #    print(intro)
>  #   user_input = raw_input(request)
>   #  print(responseHigh)
>   #  print(request)
>   #  user_input = raw_input(request)
>   #  print(responseLow)
>   #  user_input = raw_input(request)
>   #  print(responseCorrect)
>   #  print(goodbye)
>
> if __name__ == '__main__':
>     main()[/code]

According to https://en.wikipedia.org/wiki/Unit_testing:
"...one can view a unit as the smallest testable part of an application"

This is frequently a function, but certainly nothing smaller.  So  your
program is too monolithic to write multiple unit tests for.  You need to
refactor your program to make it more testable.

1) have a way to eliminate the calls to random.randint().
2) separate out the calculation from the input and output
    There has to be a better way to do this than pexpect.
    One way (probably still not the best) is to replace the print
statement and the input calls with function calls to something that the
test overrides.

Now the question of what could you possibly do in 6 tests.

Once the code has been refactored into several functions, one of those
functions probably picks the original random number.  So you can test
that function by repeatedly calling it and making sure that every
return value is a number within the specified range.

A second test might be to make sure that you get exactly 5 wrong
guesses.

A third test might be to make sure that several pre-selected sequences
of guesses elicit the right responses.  So the test might be driven from
a tuple consisting of the number, then a series of tuples where each of
the subtuples is a guess and an expected response.

A fourth test might be to stuff invalid data into the simulated input,
and make sure the program behaves as expected.  Probably throwing an
exception like it does now isn't the expected behavior.

I've run out of ideas.  But several of these could be considered
multiple tests anyway.

-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#54972

FromTerry Reedy <tjreedy@udel.edu>
Date2013-09-28 14:47 -0400
Message-ID<mailman.431.1380394053.18130.python-list@python.org>
In reply to#54924
On 9/28/2013 12:52 AM, melwin9@gmail.com wrote:
[How can I test...]

> import random
>
> intro = 'I have chosen a number from 1-10'
> request = 'Guess a number: '
> responseHigh = "That's too high."
> responseLow  = "That's too low."
> responseCorrect = "That's right!"
> goodbye = 'Goodbye and thanks for playing!'
>
> print(intro)
>
> def main():
>      guessesTaken = 0
>      number = random.randint(1, 10)
>      while guessesTaken < 5:
>          print(request)
>          guess = input()
>          guess = int(guess)
>
>          guessesTaken = guessesTaken + 1
>
>          if guess < number:
>              print(responseLow)
>
>          if guess > number:
>              print(responseHigh)
>
>          if guess == number:
>              break
>
>      if guess == number:
>              guessesTaken = str(guessesTaken)
>              print(responseCorrect + '! You guessed my number in ' + guessesTaken + ' guesses!')
>
>      if guess != number:
>          number = str(number)
>          print(goodbye + ' The number I was thinking of was ' + number)

> if __name__ == '__main__':
>      main()

To expand on Dave's answer, I would refactor main() as below.

Note 1. I add 'allowed' so you can easily change the number or let the 
user decide the difficulty. One can always guess right in at most 4 tries.

Note 2. I am presuming that you are using 3.x.

allowed = 5

def getguess(target, allowed):
   tries = 0
   while tries < allowed:
     tries += 1
     guess = int(input(request))
     if guess < target:
       print(response_low)
     elif guess > target:
       print(response_high)
     else:
       return guess, tries

def main(target)
   guess, tries = getguess(target, allowed)
   if guess == number:
     print(responseCorrect + '! You guessed my number in ' + tries + ' 
guesses!')
   else:
     print(goodbye + ' The number I was thinking of was ' + number)

if __name__ == '__main__':
   main(random.randint(1, 10))

To test a function, you must be able to control inputs and access 
outputs. Unfortunately, this makes testing simple beginner programs that 
turn user input and random numbers input into screen output harder, in a 
way, than testing complicated math functions, such as one that 
approximates the derivative of a function as a point.

One way to control user input for getguess is to put something like the 
following (untested) in your test module. (Ignore print for the moment.)

class IntInput:
   "Replace input() that should return int as string."
   def __init__(self, ints, print=None)
     "Ints must be a sequence of ints"
     self.i = -1  # so 0 after first increment
     self.ints = ints
     self.print = print
   def input(prompt):
     "Maybe save prompt, return str(int)."
     if self.print:
       self.print(prompt)
     i = self.i + 1
     self.i = i
     return str(self.ints[i])

In test methods, inject a mock input into the tested module with 
something like
         g.input = IntInput((5,3,2,1)).input
where the sequence passed is appropriate for the target and the response 
you want. This will be sufficient to test most of the operation of getguess.

(I am aware that some would say that IntInput should be a context 
manager with an exit method that restores g.input. I do not think that 
this complication is needed for this post.)

To test the getguess prompts and main output, collect output lines with 
something like

class Screen:
   def __init__(self):
     self.lines = []
   def print(self, line):
     self.lines.append(line)

   screen = Screen()
   g.input = IntInput((5,3,2,1), screen.print).input
   # Test that screen.lines is as it should be.
   # Be careful that actual and expected both have
   # or both do not have terminal \n.

For testing main, in test_xxx methods,
     screen = Screen
     g.print = screen.print
     # test screen.lines in

Another approach is to replace sys.stdin/out as is done in 
test.support.capture_stdin/out, but the latter are considered internal 
functions not for general use, and this method seems more complicated.

random and random.randint could be mocked, but this in not needed for 
this program with the randint call moved out of main().

---
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#55045

Frommelwin9@gmail.com
Date2013-09-29 18:46 -0700
Message-ID<0dfb1b91-766c-47d5-9708-84b88838d247@googlegroups.com>
In reply to#54972
Hi Terry & Dave,

Thanks for the suggestions. I am running Python 2.7 and when I tried the code above it said def main(target) <- invalid syntax. I was told to use pexpect by my professor which is why I started to use that for the tests. As for the test suggestions, I will try to come up wit those tests with my current code but again idk how to do it in pexpect which was asked of me.

On Saturday, September 28, 2013 2:47:20 PM UTC-4, Terry Reedy wrote:
> On 9/28/2013 12:52 AM, mel wrote:
> 
> [How can I test...]
> 
> 
> 
> > import random
> 
> >
> 
> > intro = 'I have chosen a number from 1-10'
> 
> > request = 'Guess a number: '
> 
> > responseHigh = "That's too high."
> 
> > responseLow  = "That's too low."
> 
> > responseCorrect = "That's right!"
> 
> > goodbye = 'Goodbye and thanks for playing!'
> 
> >
> 
> > print(intro)
> 
> >
> 
> > def main():
> 
> >      guessesTaken = 0
> 
> >      number = random.randint(1, 10)
> 
> >      while guessesTaken < 5:
> 
> >          print(request)
> 
> >          guess = input()
> 
> >          guess = int(guess)
> 
> >
> 
> >          guessesTaken = guessesTaken + 1
> 
> >
> 
> >          if guess < number:
> 
> >              print(responseLow)
> 
> >
> 
> >          if guess > number:
> 
> >              print(responseHigh)
> 
> >
> 
> >          if guess == number:
> 
> >              break
> 
> >
> 
> >      if guess == number:
> 
> >              guessesTaken = str(guessesTaken)
> 
> >              print(responseCorrect + '! You guessed my number in ' + guessesTaken + ' guesses!')
> 
> >
> 
> >      if guess != number:
> 
> >          number = str(number)
> 
> >          print(goodbye + ' The number I was thinking of was ' + number)
> 
> 
> 
> > if __name__ == '__main__':
> 
> >      main()
> 
> 
> 
> To expand on Dave's answer, I would refactor main() as below.
> 
> 
> 
> Note 1. I add 'allowed' so you can easily change the number or let the 
> 
> user decide the difficulty. One can always guess right in at most 4 tries.
> 
> 
> 
> Note 2. I am presuming that you are using 3.x.
> 
> 
> 
> allowed = 5
> 
> 
> 
> def getguess(target, allowed):
> 
>    tries = 0
> 
>    while tries < allowed:
> 
>      tries += 1
> 
>      guess = int(input(request))
> 
>      if guess < target:
> 
>        print(response_low)
> 
>      elif guess > target:
> 
>        print(response_high)
> 
>      else:
> 
>        return guess, tries
> 
> 
> 
> def main(target)
> 
>    guess, tries = getguess(target, allowed)
> 
>    if guess == number:
> 
>      print(responseCorrect + '! You guessed my number in ' + tries + ' 
> 
> guesses!')
> 
>    else:
> 
>      print(goodbye + ' The number I was thinking of was ' + number)
> 
> 
> 
> if __name__ == '__main__':
> 
>    main(random.randint(1, 10))
> 
> 
> 
> To test a function, you must be able to control inputs and access 
> 
> outputs. Unfortunately, this makes testing simple beginner programs that 
> 
> turn user input and random numbers input into screen output harder, in a 
> 
> way, than testing complicated math functions, such as one that 
> 
> approximates the derivative of a function as a point.
> 
> 
> 
> One way to control user input for getguess is to put something like the 
> 
> following (untested) in your test module. (Ignore print for the moment.)
> 
> 
> 
> class IntInput:
> 
>    "Replace input() that should return int as string."
> 
>    def __init__(self, ints, print=None)
> 
>      "Ints must be a sequence of ints"
> 
>      self.i = -1  # so 0 after first increment
> 
>      self.ints = ints
> 
>      self.print = print
> 
>    def input(prompt):
> 
>      "Maybe save prompt, return str(int)."
> 
>      if self.print:
> 
>        self.print(prompt)
> 
>      i = self.i + 1
> 
>      self.i = i
> 
>      return str(self.ints[i])
> 
> 
> 
> In test methods, inject a mock input into the tested module with 
> 
> something like
> 
>          g.input = IntInput((5,3,2,1)).input
> 
> where the sequence passed is appropriate for the target and the response 
> 
> you want. This will be sufficient to test most of the operation of getguess.
> 
> 
> 
> (I am aware that some would say that IntInput should be a context 
> 
> manager with an exit method that restores g.input. I do not think that 
> 
> this complication is needed for this post.)
> 
> 
> 
> To test the getguess prompts and main output, collect output lines with 
> 
> something like
> 
> 
> 
> class Screen:
> 
>    def __init__(self):
> 
>      self.lines = []
> 
>    def print(self, line):
> 
>      self.lines.append(line)
> 
> 
> 
>    screen = Screen()
> 
>    g.input = IntInput((5,3,2,1), screen.print).input
> 
>    # Test that screen.lines is as it should be.
> 
>    # Be careful that actual and expected both have
> 
>    # or both do not have terminal \n.
> 
> 
> 
> For testing main, in test_xxx methods,
> 
>      screen = Screen
> 
>      g.print = screen.print
> 
>      # test screen.lines in
> 
> 
> 
> Another approach is to replace sys.stdin/out as is done in 
> 
> test.support.capture_stdin/out, but the latter are considered internal 
> 
> functions not for general use, and this method seems more complicated.
> 
> 
> 
> random and random.randint could be mocked, but this in not needed for 
> 
> this program with the randint call moved out of main().
> 
> 
> 
> ---
> 
> Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#55046

FromSteven D'Aprano <steve@pearwood.info>
Date2013-09-30 02:55 +0000
Message-ID<5248e816$0$2865$c3e8da3$76491128@news.astraweb.com>
In reply to#55045
On Sun, 29 Sep 2013 18:46:30 -0700, melwin9 wrote:

> Hi Terry & Dave,
> 
> Thanks for the suggestions. I am running Python 2.7 and when I tried the
> code above it said def main(target) <- invalid syntax. 


Did you fix the invalid syntax? Until you fix it, you're blocked.

As a programmer, it is completely normal to occasionally make a typo or 
other trivial mistake that leads to invalid syntax. It's not worth 
mentioning. You just fix it and move on.

It's a bit like being a cook. The recipe says, "add one tablespoon of 
sugar", and you say "well I tried, but the spoon bangs on the lid of the 
jar." The solution is to take the lid off first. The recipe doesn't 
mention this, just like the recipe doesn't say "take the spoon out of the 
cutlery drawer". You just do it.

If you don't understand the syntax error you got, firstly try to compare 
the bad syntax

def main(target)
    blah blah blah


with working functions that don't give syntax errors

def function(arg):
    blah blah blah


Can you spot the difference? Hint: the syntax error will show an arrow ^ 
pointing at the spot where it notices a problem. Can you fix the problem? 
If so, great, move on! If not, ask for help, but remember to COPY AND 
PASTE the entire traceback, starting with the line

Traceback (most recent call last)

all the way to the end of the error message.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#55050

Frommelwin9@gmail.com
Date2013-09-29 21:19 -0700
Message-ID<d239fcf5-5730-4017-969d-bd6362a521d1@googlegroups.com>
In reply to#55046
Hi Dave,

Yeah I found the silly mistake lol thanks for that. making progress.


Guess a number: 5
That's too high.
Guess a number: 4
That's too high.
Guess a number: 3
Traceback (most recent call last):
  File "guess.py", line 34, in <module>
    main(random.randint(1, 10)) 
  File "guess.py", line 29, in main
    print(responseCorrect + '! You guessed my number in ' + tries + 'guesses!')
TypeError: cannot concatenate 'str' and 'int' objects

[code]import random

intro = 'I have chosen a number from 1-10'
request = 'Guess a number: '
responseHigh = "That's too high."
responseLow  = "That's too low."
responseCorrect = "That's correct!"
responseWrong = "Wrong, The correct number is "
guessTaken = "Your number of guesses were "
goodbye = ' Goodbye and thanks for playing!'

allowed = 5

def getguess(target, allowed):
   tries = 0
   while tries < allowed:
     tries += 1
     guess = int(input(request))
     if guess < target:
       print(responseLow)
     elif guess > target:
       print(responseHigh)
     else:
       return guess, tries

def main(target):
   guess, tries = getguess(target, allowed)
   if guess == target:
     print(responseCorrect + '! You guessed my number in ' + tries + 'guesses!')
   else:
     print(goodbye + ' The number I was thinking of was ' + number)

if __name__ == '__main__':
   main(random.randint(1, 10)) [/code]


On Sunday, September 29, 2013 10:55:19 PM UTC-4, Steven D'Aprano wrote:
> On Sun, 29 Sep 2013 18:46:30 -0700, melwin9 wrote:
> 
> 
> 
> > Hi Terry & Dave,
> 
> > 
> 
> > Thanks for the suggestions. I am running Python 2.7 and when I tried the
> 
> > code above it said def main(target) <- invalid syntax. 
> 
> 
> 
> 
> 
> Did you fix the invalid syntax? Until you fix it, you're blocked.
> 
> 
> 
> As a programmer, it is completely normal to occasionally make a typo or 
> 
> other trivial mistake that leads to invalid syntax. It's not worth 
> 
> mentioning. You just fix it and move on.
> 
> 
> 
> It's a bit like being a cook. The recipe says, "add one tablespoon of 
> 
> sugar", and you say "well I tried, but the spoon bangs on the lid of the 
> 
> jar." The solution is to take the lid off first. The recipe doesn't 
> 
> mention this, just like the recipe doesn't say "take the spoon out of the 
> 
> cutlery drawer". You just do it.
> 
> 
> 
> If you don't understand the syntax error you got, firstly try to compare 
> 
> the bad syntax
> 
> 
> 
> def main(target)
> 
>     blah blah blah
> 
> 
> 
> 
> 
> with working functions that don't give syntax errors
> 
> 
> 
> def function(arg):
> 
>     blah blah blah
> 
> 
> 
> 
> 
> Can you spot the difference? Hint: the syntax error will show an arrow ^ 
> 
> pointing at the spot where it notices a problem. Can you fix the problem? 
> 
> If so, great, move on! If not, ask for help, but remember to COPY AND 
> 
> PASTE the entire traceback, starting with the line
> 
> 
> 
> Traceback (most recent call last)
> 
> 
> 
> all the way to the end of the error message.
> 
> 
> 
> 
> 
> 
> 
> -- 
> 
> Steven

[toc] | [prev] | [next] | [standalone]


#55052

FromTerry Reedy <tjreedy@udel.edu>
Date2013-09-30 02:08 -0400
Message-ID<mailman.474.1380521312.18130.python-list@python.org>
In reply to#55050
On 9/30/2013 12:19 AM, melwin9@gmail.com wrote:
> Hi Dave,
>
> Yeah I found the silly mistake lol thanks for that. making progress.
>
>
> Guess a number: 5
> That's too high.
> Guess a number: 4
> That's too high.
> Guess a number: 3
> Traceback (most recent call last):
>    File "guess.py", line 34, in <module>
>      main(random.randint(1, 10))
>    File "guess.py", line 29, in main
>      print(responseCorrect + '! You guessed my number in ' + tries + 'guesses!')
> TypeError: cannot concatenate 'str' and 'int' objects

This is what 'untested' means ;-)

> [code]import random
>
> intro = 'I have chosen a number from 1-10'
> request = 'Guess a number: '
> responseHigh = "That's too high."
> responseLow  = "That's too low."
> responseCorrect = "That's correct!"
> responseWrong = "Wrong, The correct number is "
> guessTaken = "Your number of guesses were "
> goodbye = ' Goodbye and thanks for playing!'
>
> allowed = 5
>
> def getguess(target, allowed):
>     tries = 0
>     while tries < allowed:
>       tries += 1
>       guess = int(input(request))
>       if guess < target:
>         print(responseLow)
>       elif guess > target:
>         print(responseHigh)
>       else:
>         return guess, tries
>
> def main(target):
>     guess, tries = getguess(target, allowed)
>     if guess == target:
>         print(responseCorrect + '! You guessed my number in ' + tries + 'guesses!')

Either change 'tries' to 'str(tries)' or replace the statement with

        print(responseCorrect, 'You guessed my number in', tries, 
'guesses!')

There is no need to create a single string before the print.

>     else:
>       print(goodbye + ' The number I was thinking of was ' + number)

ditto

>
> if __name__ == '__main__':
>     main(random.randint(1, 10)) [/code]

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#55107

Frommelwin9@gmail.com
Date2013-09-30 12:54 -0700
Message-ID<64c1fa97-ace1-4fee-83b0-cf5fd7230e82@googlegroups.com>
In reply to#54924
Lol, im starting to get the hang out of, onto the next hurdle, i looked up the error and it says the data is none?

Traceback (most recent call last):
  File "guess.py", line 34, in <module>
    main(random.randint(1, 10)) 
  File "guess.py", line 27, in main
    guess, tries = getguess(target, allowed)
TypeError: 'NoneType' object is not iterable


On Saturday, September 28, 2013 12:52:26 AM UTC-4, mel...@gmail.com wrote:
> Hey,
> 
> 
> 
> How do i go about coming up/coding tests for this program below. Not sure how to even approach writing about 5 tests for it.
> 
> 
> 
> Initially I had this for the test but its not working well.
> 
> 
> 
> Test was name test_guess.py (Code Below)
> 
> 
> 
> [code]
> 
> from unittest import TestCase 
> 
> import pexpect as pe 
> 
> 
> 
> import guess as g 
> 
> import random 
> 
> 
> 
> random_number = random.randrange(1, 10) 
> 
> correct = False 
> 
> 
> 
> class GuessTest(TestCase): 
> 
>     def setUp(self): 
> 
>         self.intro = 'I have chosen a number from 1-10' 
> 
>         self.request = 'Guess a number: ' 
> 
>         self.responseHigh = "That's too high." 
> 
>         self.responseLow  = "That's too low." 
> 
>         self.responseCorrect = "That's right!" 
> 
>         self.goodbye = 'Goodbye and thanks for playing!' 
> 
>         
> 
>     def test_main(self): 
> 
>         #cannot execute main now because it will 
> 
>         #require user input 
> 
>         from guess import main 
> 
>         
> 
>     def test_guessing_hi_low_4(self): 
> 
>         # Conversation assuming number is 4 
> 
>         child = pe.spawn('python guess.py') 
> 
>         child.expect(self.intro,timeout=5) 
> 
>         child.expect(self.request,timeout=5) 
> 
>         child.sendline('5') 
> 
>         child.expect(self.responseHigh,timeout=5) 
> 
>         child.sendline('3') 
> 
>         child.expect(self.responseLow,timeout=5) 
> 
>         child.sendline('4') 
> 
>         child.expect(self.responseCorrect,timeout=5) 
> 
>         child.expect(self.goodbye,timeout=5) 
> 
> 
> 
> 
> 
>     def __init__(self): 
> 
>         self.number = random.randint(0,10) 
> 
>         HIGH = 1 
> 
>         LOW = 2 
> 
>         OK = 3 
> 
> 
> 
>     def guess(self, number): 
> 
>         if number > self.number: 
> 
>          return self.HIGH 
> 
>         if number < self.number: 
> 
>          return self.LOW 
> 
>         return self.OK 
> 
> 
> 
>     def test_guesstoolow(self): 
> 
>         while not correct: 
> 
>             guess = input("What could it be?") 
> 
>             if guess == random_number: 
> 
>                 print "Congrats You Got It" 
> 
>                 correct = True 
> 
>             elif guess > random_number: 
> 
>                 print "To High" 
> 
>             elif guess < random_number: 
> 
>                 print "To Low" 
> 
>             else: 
> 
>                 print "Try Again"  [/code]
> 
> 
> 
> Python code for game below
> 
> 
> 
> [code]
> 
> import random
> 
> 
> 
> intro = 'I have chosen a number from 1-10'
> 
> request = 'Guess a number: '
> 
> responseHigh = "That's too high."
> 
> responseLow  = "That's too low."
> 
> responseCorrect = "That's right!"
> 
> goodbye = 'Goodbye and thanks for playing!'
> 
> 
> 
> print(intro)
> 
> 
> 
> def main():
> 
>     guessesTaken = 0
> 
>     number = random.randint(1, 10)
> 
>     while guessesTaken < 5:
> 
>         print(request)
> 
>         guess = input()
> 
>         guess = int(guess)
> 
> 
> 
>         guessesTaken = guessesTaken + 1
> 
> 
> 
>         if guess < number:
> 
>             print(responseLow) 
> 
> 
> 
>         if guess > number:
> 
>             print(responseHigh)
> 
> 
> 
>         if guess == number:
> 
>             break
> 
> 
> 
>     if guess == number:
> 
>             guessesTaken = str(guessesTaken)
> 
>             print(responseCorrect + '! You guessed my number in ' + guessesTaken + ' guesses!')
> 
> 
> 
>     if guess != number:
> 
>         number = str(number)
> 
>         print(goodbye + ' The number I was thinking of was ' + number)
> 
> 
> 
> ##def main():
> 
> #    print(intro)
> 
>  #   user_input = raw_input(request)
> 
>   #  print(responseHigh)
> 
>   #  print(request)
> 
>   #  user_input = raw_input(request)
> 
>   #  print(responseLow)
> 
>   #  user_input = raw_input(request)
> 
>   #  print(responseCorrect)
> 
>   #  print(goodbye)
> 
> 
> 
> if __name__ == '__main__':
> 
>     main()[/code]

[toc] | [prev] | [next] | [standalone]


#55109

FromMRAB <python@mrabarnett.plus.com>
Date2013-09-30 21:08 +0100
Message-ID<mailman.503.1380571692.18130.python-list@python.org>
In reply to#55107
On 30/09/2013 20:54, melwin9@gmail.com wrote:
> Lol, im starting to get the hang out of, onto the next hurdle, i looked up the error and it says the data is none?
>
> Traceback (most recent call last):
>    File "guess.py", line 34, in <module>
>      main(random.randint(1, 10))
>    File "guess.py", line 27, in main
>      guess, tries = getguess(target, allowed)
> TypeError: 'NoneType' object is not iterable
>
[snip]
Look at 'getguess'.

If the user guess correctly within the number of allowed attempts, the
function returns (guess, tries), but what if the user runs out of
attempts?

[toc] | [prev] | [next] | [standalone]


#55111

FromDave Angel <davea@davea.name>
Date2013-09-30 20:20 +0000
Message-ID<mailman.504.1380572446.18130.python-list@python.org>
In reply to#55107
On 30/9/2013 15:54, melwin9@gmail.com wrote:

> Lol, im starting to get the hang out of, onto the next hurdle, i looked up the error and it says the data is none?
>
> Traceback (most recent call last):
>   File "guess.py", line 34, in <module>
>     main(random.randint(1, 10)) 
>   File "guess.py", line 27, in main
>     guess, tries = getguess(target, allowed)
> TypeError: 'NoneType' object is not iterable
>
>

Please don't top-post.  Further, if you insist on using a buggy app like
googlegroups, at least remove all the stupid double-spacing.

Do you know how to interpret this error message?  The line that fails is
    guess, tries = getguess(target, allowed)


So can you tell what the None data is?  You're doing a tuple-unpack on
the left side of the equals, so the right side needs to be a tuple,
list, or equivalent.  In specific, an iterable.

Now you reread the error, and realize that the getguess() function is
returning None.

If I were a novice, I'd start by splitting up the line with the error:

   temp =  getguess(target, allowed)
   guess, tries = temp

Then when the error complains about the second line, I'd add a print
statement:

   temp =  getguess(target, allowed)
   print(repr(temp))
   guess, tries = temp

Lacking the source code, I'm going to guess that some path through your
code is missing a return expression.

For example, you might have

def  getguess(a, b):
     if a < b:
        return a, a*b

So it'll return a tuple of two items in the if body, but without an else
clause, it simply falls off the end, and returns None.  (All functions
return something, so if you don't provide a value, None is used)


-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#55145

FromTerry Reedy <tjreedy@udel.edu>
Date2013-09-30 20:06 -0400
Message-ID<mailman.525.1380586006.18130.python-list@python.org>
In reply to#55107
On 9/30/2013 3:54 PM, melwin9@gmail.com wrote:
> Lol, im starting to get the hang out of, onto the next hurdle, i looked up the error and it says the data is none?
>
> Traceback (most recent call last):
>    File "guess.py", line 34, in <module>
>      main(random.randint(1, 10))
>    File "guess.py", line 27, in main
>      guess, tries = getguess(target, allowed)
> TypeError: 'NoneType' object is not iterable

If you have not figured it out yet, add a copy of the return within the 
while loop,
    return guess, tries
after the while loop also, so it does not return the default of None.

-- 
Terry Jan Reedy

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web