0

doctest とシェルで同じコードを使用すると、異なる出力が得られます。
いくつかのテストを実行する a() という関数があります。
これらと同じテストが doctest (test() ) で使用されます。
a() を使用すると、OBJECT-BLANKLINE-OBJECT が返されますが、test() ではエラーが発生し、最初の OBJECT のみが表示されます。
これは doctest モジュールの欠陥ですか?

上部に a() と test() の両方を含むファイル全体を次に示します。

'''
>>> u1 = User("luis@fc.up.pt", "simples")
>>> u2 = User("ana@fc.up.pt", "complicada")
>>> u2.askFriend(u1)
>>> u1.recvRequest(u2)
>>> u1.confirmFriend(u2)
>>> p1 = Post(u1, "O ultimo post", "http://www.wikipedia.org")
>>> p2 = Post(u2, "A ultima resposta", "http://www.google.com")
>>> c = Comments()
>>> c.add(p1)
>>> c.add(p2)
>>> f1 = c.search(user="ana@fc.up.pt")
>>> print(f1)
A ultima resposta
http://www.google.com
0 Gosto, 0 Nao gosto
>>> f2 = c.search(likes=1)
>>> print(f2)
<BLANKLINE>
>>> f3 = c.search(text='post')
>>> print(f3)
O ultimo post
http://www.wikipedia.org
0 Gosto, 0 Nao gosto
<BLANKLINE>
A ultima resposta
http://www.google.com
0 Gosto, 0 Nao gosto
'''

def test():
    import doctest
    doctest.testmod()

def a():
    u1 = User("luis@fc.up.pt", "simples")
    u2 = User("ana@fc.up.pt", "complicada")
    u2.askFriend(u1)
    u1.recvRequest(u2)
    u1.confirmFriend(u2)
    p1 = Post(u1, "O ultimo post", "http://www.wikipedia.org")
    p2 = Post(u2, "A ultima resposta", "http://www.google.com")
    c = Comments()
    c.add(p1)
    c.add(p2)
    f3 = c.search(text="post")
    print(f3)

import string

class User:

    def __init__(self,email,passwd):
        self.email = email
        self.passwd = passwd
        self.name = None
        self.year = None
        self.active = True
        self.recv = [] 
        self.conf = []
        self.setPassword(self.passwd)

    def __str__(self):
        if self.name == None and self.active == True:
            return str(self.email) + ':' + 'ativa'

        elif self.name != None and self.active == True:
            return str(self.name) + ':' + str(self.email) + ':' + 'ativa'

        elif self.name != None and self.active == False:
            return str(self.name) + ':' + str(self.email) + ':' + 'inativa'

        else:
            return str(self.email) + ':' + 'inativa'

    def getEmail(self):
        return self.email

    def setPassword(self,passwd):
        abc = string.ascii_lowercase
        cifra = abc[3:] + abc[:3]
        dec = list(passwd)
        passwdCif = ""
        for i in dec:
            cif = cifra[abc.find(i)]
            passwdCif += cif
        self.passwd = passwdCif

    def getPassword(self):
        return self.passwd

    def setName(self,name):
        self.name = name

    def getName(self):
        return self.name

    def setBirth(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day

    def getBirth(self):
        if self.year == None:
            return None
        else:
            return '(' + str(self.year) + ', ' + str(self.month) + ', ' + str(self.day) + ')'

    def isActive(self):
        if self.active == True:
            return True
        else:
            return False

    def setActive(self):
        self.active = True

    def setInactive(self):
        self.active = False

    def askFriend(self,u):
        self.conf.append(u)

    def recvRequest(self,u):
        self.recv.append(u)

    def confirmFriend(self,u):
        if len(self.recv) == 0:
            return None
        else:
            for i in self.recv:
                if i == u:
                    self.recv.remove(i)
                    self.conf.append(i)
                else:
                    return None


    def isFriend(self,u):
        if u in self.conf:
            return True
        elif self == u:
            return True
        else:
            return False

    def showPending(self):
        if len(self.recv) == 0:
            return None
        else:
            for i in self.recv:
                print i

    def showFriends(self):
        if len(self.conf) == 0:
            return None
        else:
            for i in self.conf:
                print i

class Post():
    def __init__(self,u,text='',link=None):
        self.u = u
        self.text = text
        self.link = link
        self.seg = None
        self.ant = None
        self.likeList = []
        self.dislikeList = []

    def __str__(self):
        if self.link == None:
            return str(self.text) + '\n' + str(len(self.likeList)) + ' Gosto, ' + str(len(self.dislikeList)) + ' Nao gosto'
        else:
            return str(self.text) + '\n' + str(self.link) + '\n' + str(len(self.likeList)) + ' Gosto, ' + str(len(self.dislikeList)) + ' Nao gosto'

    def updateText(self,text):
        self.text = text

    def updateLink(self,link):
        self.link = link

    def like(self,u):
        if (u in self.u.conf) or (u == self.u):
            if u in self.dislikeList:
                self.dislikeList.remove(u)
                self.likeList.append(u)
            elif u in self.likeList:
                return None
            else:
                self.likeList.append(u)
        else:
            return None

    def dislike(self,u):
        if (u in self.u.conf) or (u == self.u):
            if u in self.likeList:
                self.likeList.remove(u)
                self.dislikeList.append(u)
            elif u in self.dislikeList:
                return None
            else:
                self.dislikeList.append(u)
        else:
            return None

class Comments():
    def __init__(self, u=None, text='', link=None):
        self.u = u
        self.text = text
        self.link = link
        self.topo = None
        self.fim = None

    def __str__(self):
        actual = self.topo
        s = ''
        if actual == None:
            return ''
        while actual != None:
            if actual.seg == None:
                s += str(actual)
                actual = actual.seg
            elif actual.seg != None:
                s += str(actual) + '\n' + '\n'
                actual = actual.seg
        return s

    def add(self,comment):
        if self.topo == None:
            comment.ant = None
            comment.seg = None
            self.topo = comment
            self.fim = comment
        else:
            comment.ant = None
            comment.seg = self.topo
            self.topo.ant = comment
            self.topo = comment

    def remove(self,comment):
        actual = self.topo
        if (self.topo == self.fim) and (self.topo == comment):
            self.topo = None
            self.fim = None
            actual = None
        while actual!=None:
            if actual == comment:
                if actual.ant == None:
                    self.topo = actual.seg
                    actual.seg.ant = None
                elif actual.seg == None:
                    self.fim = actual.ant
                    actual.ant.seg = None
                else:
                    actual.seg.ant = actual.ant
                    actual.ant.seg = actual.seg
                break
            else:
                actual = actual.seg

    def countLike(self):
        count = 0
        actual = self.topo
        while actual != None:
            if len(actual.likeList) >= 1:
                count += 1
                actual = actual.seg
            else:
                actual = actual.seg
        return count

    def showRecentComments(self,n):
        count = 1
        actual = self.topo
        sC = ''
        if actual == None:
            return None
        while actual != None:
            if count < n:
                if actual.seg == None:
                    sC += str(actual)
                    count += 1
                    actual = actual.seg
                else:
                    sC += str(actual) + '\n' + '\n'
                    count += 1
                    actual = actual.seg
            elif count == n:
                sC += str(actual)
                count += 1
                actual = actual.seg
            elif count > n:
                break 
        print sC

    def search(self, user=None, likes=None, dislikes=None, text=None):
        result = []
        actual = self.topo
        cR = Comments()
        if actual == None:
            return None

        while actual != None:
            if user != None:
                if actual.u.email != user:
                    actual = actual.seg
                elif actual.u.email == user:
                    result.append(actual)
                    actual = actual.seg
            elif user == None:
                break
        actual = self.topo

        while actual != None:
            if likes != None:
                if likes > len(actual.likeList):
                    actual = actual.seg
                elif likes <= len(actual.likeList):
                    if actual in result:
                        actual = actual.seg
                    else:
                        result.append(actual)
                        actual = actual.seg
            elif likes == None:
                break
        actual = self.topo

        while actual != None:
            if dislikes != None:
                if dislikes > len(actual.dislikeList):
                    actual = actual.seg
                elif dislikes <= len(actual.dislikeList):
                    if actual in result:
                        actual = actual.seg
                    else:
                        result.append(actual)
                        actual = actual.seg
            elif dislikes == None:
                break
        actual = self.topo

        while actual != None:
            if text != None:
                if text not in actual.text:
                    actual = actual.seg
                elif text in actual.text:
                    if actual in result:
                        actual = actual.seg
                    else:
                        result.append(actual)
                        actual = actual.seg
            elif text == None:
                break
        if len(result) != 0:
            for i in result:
                cR.add(i)
        return cR

a() と test() の両方を使用して取得した出力は次のとおりです。

>>> a()
O ultimo post
http://www.wikipedia.org
0 Gosto, 0 Nao gosto

A ultima resposta
http://www.google.com
0 Gosto, 0 Nao gosto
>>> test()
**********************************************************************
File "__main__", line 22, in __main__
Failed example:
    print(f3)
Expected:
    O ultimo post
    http://www.wikipedia.org
    0 Gosto, 0 Nao gosto
    <BLANKLINE>
    A ultima resposta
    http://www.google.com
    0 Gosto, 0 Nao gosto
Got:
    A ultima resposta
    http://www.google.com
    0 Gosto, 0 Nao gosto
**********************************************************************
1 items had failures:
   1 of  16 in __main__
***Test Failed*** 1 failures.
>>> 

また、以前のひどく尋ねられた質問についてお詫び申し上げます。
うまくいけば、これは私と他の人を助けるでしょう.

4

1 に答える 1

2

doctestと関数の間には明らかな違いが1つあります。関数aがこれを実行している間:

# previous code
c.add(p2)
f3 = c.search(text="post")
print(f3)

あなたのdoctestはこれを行います:

# previous code
c.add(p2)
f1 = c.search(user="ana@fc.up.pt")
print(f1)
f2 = c.search(likes=1)
print(f2)
f3 = c.search(text='post')
print(f3)

そこで何が起こっているのか正確にはわかりませんが、おそらく同じことをするように関数を書く必要があります。それでも結果が異なる場合は、doctestに問題があります。それ以外の場合は、コードに問題があります。

編集:

今、私はあなたがなぜ問題を抱えているのか理解し始めました、そしてそれはひどい問題です。検索機能のすぐ上にある次の行から始まります。

actual = self.topo

Pythonがプロパティを割り当てる方法を知らないと思います。コードの後半でactualを変更してから、self.topoをactualに再度割り当てます。

actual.seg = "somevalue" # sorry, i can't remember what you did"
actual = self.topo

実際にはすでにself.topoであるため、この2行目は完全に無意味です。これはself.topoの値ではありませんが、self.topoです。

書く代わりに

actual.seg = "somevalue"

あなたはただ書くことができます

self.topo.seg = "somevalue"

どちらの行もまったく同じです。したがって、独立したプロパティactualを変更していると思っている間は、常にself.topoを変更していました。つまり、actualこれは関数の各開始時に等しくはありませんが、最後の実行時に持っていた値を常に持っていることを意味しc.searchます。

他のいくつかの関数でもこれを実行していることを確認しました。つまり、このような関数を呼び出すたびに、Commentsインスタンスcの状態を変更しています。もちろん、これにより、テストごとに異なる出力が得られます。

これをより理解しやすくするために、リストを使用した例を次に示します。

>>> a_list = ['one','two','three']
>>> b_list = a_list
>>> b_list.pop()
'three'
>>> a_list
['one', 'two']

ご覧のとおり、Allthougはb_listから要素をポップしましたが、a_listからも削除されています。これは、ステートメントb_list = a_listが文字通りb_listがa_listと同じであることを意味するためです。

お役に立てれば。

于 2012-04-04T16:04:24.130 に答える