如何用Selenium测试jQuery Ajax选项卡?

4 投票
1 回答
2158 浏览
提问于 2025-04-16 00:25

我正在用selenium测试一个django应用,其中有一个页面使用了jquery ui标签元素。其中一个标签里有一个简单的表格,列出了一些用户,这个表格是通过ajax加载的。在手动使用这个应用时,标签工作得很好,但在用selenium自动化测试时,标签的内容似乎没有加载出来!

我自己用python写测试。一开始,我使用的是selenium RC的click方法,但我从之前的测试中痛苦地学到,这个方法在处理锚点标签时相当不稳定,所以我又回到了之前用过的解决方案:使用wait_for_condition方法,并明确调用标签的点击事件(甚至加载事件!),但标签还是不工作

我现在很绝望,因为我的大部分测试都依赖于这个页面,几乎一半的测试都是在这个表格上,但可惜的是,selenium似乎搞砸了javascript的执行!
(我在这个类里还有其他测试,它们运行得很好,所以服务器端没有问题,似乎是selenium在客户端造成了这个问题)
我的测试代码大致是这样的:

class TestMyApp(TransactionTestCase):
urls = 'myapp.test_urls'

def setUp(self):
    self.verificationErrors = []
    self.selenium = selenium("localhost", 4444, "*chrome", "http://localhost:8000/")
    self.selenium.start()
    #self.selenium.set_speed(2000)
    self.selenium.window_maximize()
def test_users_list(self):
    """Test that an app's users are correctly listed"""
    sel = self.selenium
    users = []
    for u in range(settings.FREE_USER_LIMIT/2):
        users.append(self.app.users.create(name="testUser_%s"%uuid4()))

    sel.open("/")        
    sel.wait_for_page_to_load("30000")
    sel.wait_for_condition('selenium.browserbot.getCurrentWindow().jQuery("#tabs").tabs("select",1);\
    selenium.browserbot.getCurrentWindow().jQuery("#tabs").tabs("load",1);',
                             3000)
    for user in users:
        try: self.failUnless(sel.is_text_present(user.name))
        except AssertionError, e: self.verificationErrors.append(str(e))
        try: self.failUnless(sel.is_text_present(str(user.added.date())))
        except AssertionError, e: self.verificationErrors.append(str(e))
def tearDown(self):
    self.selenium.stop()
    self.assertEqual([], self.verificationErrors)

1 个回答

5

这可能有几个原因。首先,Selenium在点击链接时可能遇到了一些问题,但我其实没听说过这种情况,所以这可能性不大。听起来click()方法返回的是正常的结果,而不是“找不到元素”,对吧?当你点击时,jquery的标签页JavaScript似乎没有按预期工作。根据我的经验,这通常是同一个问题——因为Selenium执行得非常快,当JavaScript在不断渲染页面的某些部分并影响DOM时,有时当Selenium去与动态生成的页面部分(比如点击这个标签)互动时,它所要互动的部分可能依赖于其他部分,而这些部分实际上还没有完全加载。实际上,它可能只差几微秒就能完全加载,但Selenium的速度太快了。当然,你已经明白这一点了,你在等待条件上寻找标签加载的想法是对的。我的猜测是,这个等待时间可能不够长。你需要找到一种方法来判断整个用户界面标签是否加载并渲染完成。标签API是否有一些回调可以添加,以设置一个“加载完成”的变量,或者它是否暴露了这样的变量?如果找不到合适的表达式来确定用户界面标签实际上准备好被点击的时刻,这可能会有点棘手,你可以直接暂停一下,以确保页面的那部分准备好再进行互动。如果需要让它工作,我觉得在代码中使用sleep(2)甚至sleep(5)都没有问题。你可以通过在交互式解释器中启动这个场景来测试这是否真的是问题所在(Python真不错,比在Java中做这个要好得多)。逐行粘贴代码,直到遇到问题,或者在你的清理方法中注释掉selenium.stop()的调用,以及问题点之后的任何测试代码,这样就可以保持selenium窗口打开并退出。然后在交互式解释器中实例化一个selenium对象,劫持这个打开的会话:

selenium = selenium("localhost", 4444, "*chrome", "http://localhost:8000/")
selenium.sessionId = "0asdd234234023424foo" #Get this from the Se window

...这样就可以对窗口进行交互控制。然后你可以尝试执行selenium.click()或者使用selenium.get_eval('...js...')来调查那个时刻的JavaScript情况。我的猜测是,当你这样做时,click()实际上会正常工作,因为当你加载会话并输入selenium.click('blah_tab_locator')时,标签的内容都已经加载完毕并准备好了。只是当Python调用时,它的速度太快了,导致浏览器在动态渲染时跟不上。如果你手动通过selenium这样做时点击正常,那就说明是个时机问题。找到合适的wait_for_condition,或者妥协使用Python的sleep()。否则,如果这样做时点击仍然不工作,那可能是使用的定位器有问题。标签用户界面在某个部分有点击、鼠标抬起、聚焦或某种事件处理程序,也许只是需要找到正确的标签部分进行点击,或者触发正确的事件。如果不是这样,那可能就像你提到的,Selenium和Jquery UI之间有某种奇怪的交互,但这让我感到惊讶,我也很想知道。如果是这样,可以用get_eval()看看JavaScript发生了什么。不过在我看来,这听起来像是个时机问题。

撰写回答