Zitrax / nose-dep

Nosetest plugin for test dependencies. Makes it possible to let tests depend on each other and/or run in a specific order.
MIT License
2 stars 3 forks source link

Dekorator "depends" doesn't sets dependency into tests. #7

Closed humanUnit closed 7 years ago

humanUnit commented 7 years ago

Hello, please help me with my issue. I tried find framework for making dependency between tests, and I found your, but when I try to use decorator @depends my tests run in the alphabetic order.

For example:

from nosedep import depends

def test_a(): print ("Success test a")

@depends(before=test_a) or (before='test_a') or (before="test_a") def test_b(): print ("Success test b")

Also I tried @after, and used "priority", it didn't help.

Zitrax commented 7 years ago

Hi, sorry for the delay.

Note that to enable the plugin you must run the tests using --with-nosedep. Did you use that ?

humanUnit commented 7 years ago

Hello, thank you for answering me, I wrote tests, if run this tests from IDE everything okay, but decorator doesn’t work, if run from terminal nosetests --with-nosedep calendarcase.py, then I have Error NameError: global name 'reraise' is not defined http://prntscr.com/did0vb.

If I wrote "nosetests --with-nosedep" in the directory where tests located inside my project, then 0 tests will run

(env) Ekaterinas-MacBook-Pro:tests ekaterinak$ nosetests --with-nosedep

Ran 0 tests in 0.000s

OK

Zitrax commented 7 years ago

Right, I just noticed that reraise too now. So if you see that it's at least a sign that nosedep is enabled. The issue seem to be due to a change in recent versions of setuptools. I am still a bit unsure exactly which version that caused it.

But nosedep should definitely be updated to support the newer versions. I'll look into that now.

Zitrax commented 7 years ago

I have made a new release (0.4) to pypi that fix the reraise issue I saw on my side. You can try to upgrade and see if that helps.

humanUnit commented 7 years ago

Thank you! I tried to run tests end now in terminal this error > http://prntscr.com/disqfj. AttributeError: 'ContextSuite' object has no attribute 'test'.

Zitrax commented 7 years ago

Ok, I have not seen that before - but based on the traceback it seem to also be related to reraise.

Is it possible you could share some simple code that triggers this that I can debug ? It's might be a bit hard to debug it purely based on the traceback.

humanUnit commented 7 years ago

If I write all in the one module everything works fine. For example:

coding=utf-8
import unittest
from nose.tools import assert_true
from nosedep import depends
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By

class FirstTest(unittest.TestCase):

    search_field = 'lst-ib'
    lucky_button = "btnI"
    picture = "//img[@alt='Doria Shafik’s 108th Birthday']"

    def __init__(self, *args, **kwargs):
        super(FirstTest, self).__init__(*args, **kwargs)

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome(executable_path='write path here')
        cls.driver.implicitly_wait(30)
        cls.driver.maximize_window()
        cls.driver.get("https://www.google.com")

    def test_a(self):
        assert_true(self.is_element_present(By.ID, self.search_field))
        print("test a")

    @depends(after=test_a)
    def test_b(self):
        driver = self.driver
        driver.find_element(By.NAME, self.lucky_button).click()
        self.assertTrue(self.is_element_present(By.XPATH, self.picture))
        print("test b")

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()

    def is_element_present(self, how, what):
        try:
            self.driver.find_element(by=how, value=what)
        except NoSuchElementException:
            return False
        return True

if __name__ == '__main__':
    unittest.main() 

But print doesn't work, I don't know why, so I will have message in the terminal like this

(env) Ekaterinas-MacBook-Pro:tests ekaterinak$ nosetests --with-nosedep ../../test.py ..

Ran 2 tests in 23.250s

OK

When I write my code in different modules, for example:

# coding=utf-8
import unittest
from nose.tools import assert_true
from nosedep import depends
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException

class Base(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome(executable_path='write your path here')
        cls.driver.implicitly_wait(30)
        cls.driver.maximize_window()
        cls.driver.get("https://www.google.com")

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()

    def is_element_present(self, how, what):
        try:
            self.driver.find_element(by=how, value=what)
        except NoSuchElementException:
            return False
        return True

class Locators(object):

    from selenium.webdriver.common.by import By

    search_field = (By.ID, 'lst-ib')
    lucky_button = (By.NAME, "btnI")
    picture = (By.XPATH, "//img[@alt='Doria Shafik’s 108th Birthday']")

class FirstTests(Base):

    def test_a(self):
        assert_true(self.is_element_present(*Locators.search_field))
        print("test a")

    @depends(after=test_a)
    def test_b(self):
        driver = self.driver
        driver.find_element(*Locators.lucky_button).click()
        self.assertTrue(self.is_element_present(*Locators.picture))
        print("test b")

In terminal I see this:

(env) Ekaterinas-MacBook-Pro:tests ekaterinak$ nosetests --with-nosedep ../../test.py Traceback (most recent call last): File "/Users/ekaterinak/workspace/test_env/env/bin/nosetests", line 11, in sys.exit(run_exit()) File "/Users/ekaterinak/workspace/test_env/env/lib/python2.7/site-packages/nose/core.py", line 121, in init extra_args) File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/main.py", line 95, in init self.runTests() File "/Users/ekaterinak/workspace/test_env/env/lib/python2.7/site-packages/nose/core.py", line 207, in runTests result = self.testRunner.run(self.test) File "/Users/ekaterinak/workspace/test_env/env/lib/python2.7/site-packages/nose/core.py", line 50, in run wrapper = self.config.plugins.prepareTest(test) File "/Users/ekaterinak/workspace/test_env/env/lib/python2.7/site-packages/nose/plugins/manager.py", line 99, in call return self.call(*arg, *kw) File "/Users/ekaterinak/workspace/test_env/env/lib/python2.7/site-packages/nose/plugins/manager.py", line 167, in simple result = meth(arg, kw) File "/Users/ekaterinak/workspace/test_env/env/lib/python2.7/site-packages/nosedep.py", line 288, in prepareTest reraise(tt.test.exc_class, tt.test.exc_val, tt.test.tb) AttributeError: 'ContextSuite' object has no attribute 'test'

Zitrax commented 7 years ago

Thanks for the code sample, I can reproduce it. Will look into it.

Zitrax commented 7 years ago

So the problem was specific to using subclasses of unittest.TestCase, something that had not been tested before. In general nose-dep has not been tested extensively when using unittest.TestCase (nosetests does not need it) - so there could be more issues.

But I have made a new release with a fix for the specific issue you had above. So retry with v0.5 and see.

Also instead of using print to see the test running you can pass -v to nosetests. So something like: nosetests -v test.py. ( There is some way to see the print output too though, but I don't remember exactly how now ).

humanUnit commented 7 years ago

Thank you! Now it works.

Only if I use in my tests array in function, terminal shows to me error. But probably it not necessary with using command nosetests -v test.py instead of using print

Some thing like

class FirstTests(Base):

    def test_a(self):
        print "\n" + str(test_cases(0))
        assert_true(self.is_element_present(*Locators.search_field))
        print("test a")

    @depends(after=test_a)
    def test_b(self):
        print "\n" + str(test_cases(1))
        driver = self.driver
        driver.find_element(*Locators.lucky_button).click()
        self.assertTrue(self.is_element_present(*Locators.picture))
        print("test b")

def test_cases(number):
    return testCases[number]

testCases = [
    # Login page
    # [severity, description]
    ['Blocker', 'Open google page'],
    ['Moderate', 'Button lucky click']
]

In terminal

(env) Ekaterinas-MacBook-Pro:tests ekaterinak$ nosetests --with-nosedep -v ../../test.py test_a (test.FirstTests) ... ok test_b (test.FirstTests) ... ok test.test_cases ... ERROR

ERROR: test.test_cases

Traceback (most recent call last): File "/Users/ekaterinak/workspace/test_env/env/lib/python2.7/site-packages/nose/case.py", line 197, in runTest self.test(*self.arg) TypeError: test_cases() takes exactly 1 argument (0 given) -------------------- >> begin captured logging << -------------------- selenium.webdriver.remote.remote_connection: DEBUG: DELETE http://127.0.0.1:53378/session/3868e2b8785200c29f8d9f8ce89d47ea {"sessionId": "3868e2b8785200c29f8d9f8ce89d47ea"} selenium.webdriver.remote.remote_connection: DEBUG: Finished Request --------------------- >> end captured logging << ---------------------


Ran 3 tests in 20.397s

FAILED (errors=1)

Zitrax commented 7 years ago

Good :) And thanks for reporting.

Regarding your comment I am not 100% sure what you meant, but nosetests will treat all functions that start with the string 'test' as tests, thus def test_cases will be executed as a test. You should name it something else if you just want a helper function.

humanUnit commented 7 years ago

I renamed name of the function test_cases and everything work grate now. Thank you!