Best practice for ensuring test methods order - django-testing

Django 1.9. I want to test that input forms are invisible normally. And only when a user presses toggle menu button, login and password input elements appear.
The problem is that this is all about methods of a class. I want to be sure that one method executes before another. I have found this solution with 0 and 1 in method names.
class FuncTestTablets(TestCase):
#classmethod
def setUpClass(cls):
pass
#classmethod
def tearDownClass(cls):
pass
def test_0_tablets_login_input_form_absent(self):
# At home page with tablet screen size Edith sees no login input element.
## 0 is for stating explicitly that this test goes before the ones with 1 in their name.
self.browser.get('http://localhost:8000')
login_input = self.browser.find_element_by_id('login')
self.assertFalse(login_input.is_displayed(), "Login input element is visible on large devices")
def test_1_tablets_login_input_form_present_when_menu_button_pressed(self):
# At home page Edith presses menu button and login input appears.
## 1 is for stating explicitly that this test goes after the ones with 0 in their name.
menu_button = self.browser.find_element_by_class_name('navbar-toggle')
menu_button.click()
login_input = self.browser.find_element_by_id('login')
self.assertTrue(login_input.is_displayed(), "Login input element is not visible on tablet devices when menu button is pressed.")
This seems to work. Could you tell me is there some generally known methodology for such cases. Maybe some best practice.
I've just started Django and I don't think that my solution is at once the best.
That's why I decided to ask you. Thank you in advance.

Best practice is that the order of your test methods does not matter at all and if you inherit from django.test.TestCase, it should not matter. I have, however, been in the situation where I wanted to test a feature 'foo' in one method and then, for convenience (like not having to wrap it in try-except), assume that it is working properly in other methods that test something else ('bar').
I named my test methods
test_a_foo
test_b_bar
This seems more appropriate then using numbers because tests are executed in lexicographic order where, e.g.
test_11_eleven
is executed before
test_2_two
If you then have to insert another test later, you can still change the names to:
test_b1_first_b
test_b2_second_b

Related

Apex, Dynamic action, Confirm action, not picking up correct text - what am I missing?

I'm obviously missing something and hoping someone might be able to help.
I've an Interactive Grid, and a button.
When the button is pressed the dynamic action on the button has 2 steps.
Action 1 - Execute Javascript to take a value from one of the IG cells and put it into a page item.
Action 2 - Confirm Action - Are you sure you wish to delete &P10_JOB_ID.
I've made the page item, &P10_JOB_ID, visible and I can see the value has correctly been changed to the value from the IG.
I write P10_JOB_ID into a database table - I get the correct value
But the confirm message isn't picking up the correct value from P10_JOB_ID.
Namely it uses the value in P10_JOB_ID when the page starts, but then as I move around the IG pressing the button and changing the value of P10_JOB_ID, the text in the confirm message never changes.
Can anyone suggest what I might have missed, I'm baffled.
Thanks a lot
Substitutions like &P10_JOB_ID. are made when the page is rendered, not dynamically, so reflect the value at time of page load.
You will need to use Javascript to perform the conform action, something like:
apex.page.confirm ('Are you sure you wish to delete ' + $v('P10_JOB_ID') + '?', 'DELETE');
$v is an APEX Javascript function that returns the current value of a page item.
I used 'DELETE' as an example of a request value; you may want to do something different here.
Ok - having the setting of value and confirm as 2 separate actions is what causes the problem.
As per fac586
That is the expected behaviour. Static text substitutions are performed once during page show processing. They are not evaluated dynamically in the browser at runtime as values change.
Drop the second action and extend the first to display the confirm dialog using the apex.message.confirm JS API method, accessing the item value using the $v shorthand method.

Karate UI automation, is it possible to make locators dynamic

Thanks Peter for API,Perf karate framework.
Now I am trying UI automation and it looks perfect as of now.
I have below question:
I have a menu bar with 15 items in it. they are named as following:
-Home
-Account
-groups
-settings
etc etc.
Locator for each one is like this "a[name=Home]" , "a[name=Account]", "a[name=groups]" . So ony the part after name= is something that is dynamic in nature. So my question is that is it possible to somehow make this dynamic locator?
I have written a called feature in which i have written steps to login and select a menu item. and I want to pass the menu item from calling feature in json like below:
if I want to click on Account menu
* call read(menuItem.feature) {menuItem: Account}
menuItem.feature looks something like below:
Given url 'xyz'
And input (username, userID)
And input (password, password)
And click("button[name=login]")
And click("a[name=Home]")
Here I want to make Home as dynamic in last click step on menuItem.feature so that I can pass other menu items and reuse all above steps/feature file to login everytime with different menu items passed from calling feature file in json{.
Again its just a query. I have currently written multiple scenarios to click on menu item and then in calling feature I call the called feature with tags like #Home,#account etc. and this works perfectly fine.
Also if there is any other better way to achieve this then please suggest
Yes. Let me put it this way, the things you see such as input('foo', 'bar') is pure JS behind the scenes. So normal programming-language rules apply. For example:
* def dynamic = 'foo'
* def locator = 'a[name=' + dynamic + ']'
* input(locator, 'some value')

Selenium Python Behave framework - How do I click on an element_by _id

I am working with Behave framework in Python, which i have not used before, and I am not sure how I can click on an element_by_id. There is a cookie popup that I need to get around before I can send login keys.
This is my .features file:
Feature:
Login Functionality
Scenario: I can login
When visit url "https://example.com"
When I click on the button "accept-cookie-notification"
When field with name "user_email_login" is given "#gmail.com"
When field with name "user_password" is given "password"
Then title becomes "Dashboard"
Here is my .py file:
Steps
#when('visit url "{url}"')
def step(context, url):
context.browser.get(url)
time.sleep(5)
#when('I click on the button "{selector}"')
def step(context, selector,):
elem = context.driver.find_element_by_id("selector")
elem.submit()
time.sleep(5)
#when('field with name "{selector}" is given "{value}"')
def step(context, selector, value):
elem = context.browser.find_element_by_id(selector)
elem.send_keys(value)
elem.submit()
time.sleep(5)
#then('title becomes "{title}"')
def step(context, title):
assert context.browser.title == title
Also I will need to do element_by_css and xpath later on.
Thank you in advance for any help.
Working with Selenium is very simple if you are using Behave. Just install behave-webdriver package https://pypi.org/project/behave-webdriver/ It's a step library with a wide set of already defined steps with given-when-then decorators like: I click on the element "{element}" and you can use both id,css and XPath as {element} parameter. You do not need to implement anything, just use predefined steps in your scenarios. Here are my code examples:
Scenario: A user can log in.
Given the base url is "http://my_site:3000"
And I open the site "/#/login"
And the element "#email" is visible
When I add "my#email.com" to the inputfield "#email"
And I add "1234567" to the inputfield "#password"
And I click on the button "#loginButton"
Then I wait on element "//nav-toolbar//span[contains(text(),'Myself')]" to be visible
And I expect that the attribute "label" from element "#loggedUser" is "Finally, we made it!"
And please do not forget to add handling context.behave_drive in your environment.py methods before_all() and after_all() as described in the HOWTO page above.
What you need is read some documentation about, try to take a look on something like taht where you have the most common commands
http://allselenium.info/python-selenium-commands-cheat-sheet-frequently-used/

web2py SQLFORM accepting too fast

I have a web2py SQLFORM that gets generated and returned by an AJAX call and the form is put in a DIV I defined.. I want that SQLFORM to be an update form, not an insert form. The problem is the form immediately runs it's accept function once it is written to that DIV. This doesn't happen if the form is for inserting, only updating. That initial accept fails and hitting the submit button does not allow for a second accept.
I don't know why the accept fails or why it happens immediately.
heres the JavaScript function that makes the AJAX call
function displayForm(currID){
//Remove everything from the DIV we want to use
$('#window').empty();
//Call the ajax to bring down the form to update the series
ajax('{{=URL('newForm')}}/'+currID,
[], 'window');
}
And here is the newForm controller
def newSerForm():
record = db.myTable(request.args[0])
form = SQLFORM(db.myTable, record, fields=['series_name','image_thumbnail'])
if form.accepts(request.vars,session):
print 'Series update successful!'
else:
print 'Series update Failed...'
return form
displayForm is fired by clicking a button and once you do the form accepts and fails and the submit button doesn't work again. Is there a way to make an SQLFORM do this? The weird thing is if I change this to make inserts into myTable, it works fine. It behaves exactly as it should. But doing it this way doesn't work.
Ok now this is where it gets weird.
I tried to achieve the same functionality here with a totally different approach, an iFrame. I made new functions in my controllers that create the form based on request.args[0]. looks like this
def editEntry():
print request.args[0]
record = db.myTable(request.args[0])
form = SQLFORM(db.CC_user_submission, record, fields=['series_name', 'image_thumbnail']).process()
return dict(form=form)
And then a corresponding HTML page that just displays form. What could be simpler right? I go to that page based on a link that gives the correct argument. Take me to a page with a form for updating. Updating works perfect. Great, now lets put it in an iFrame instead of linking to it. I put it in an iFrame on the original page. Open up the iFrame. Doesn't work. I have no idea what is going is there any part of an explanation to this?
By using the iFrame method I actually got this one to work. Since it required an iFrame to be appended with jQuery which needs quotes and the iFrame URL which also needs quotes, the notation got pretty confusing but it's doable. Looked like this:
var myURL = "{{=URL('editEntry')}}/"+idArg.toString();
$('#window').append("<iframe src = " + myURL + " width='450' height='400'> </iframe>");
It's not pretty but it works.

Assert css locator is equal to it's expected value

I'm doing some drag and drop js testing with selenium-client. It works (taking screengrabs before and after clearly show the elements to switch places), but I'm having trouble programatically asserting the change happened.
Am I mental, or can I not do something like:
selenium.assert_equal("css locator", "expected id of element")
which, in this case, would look something like:
selenium.assert_equal("css=li:nth-child(1)", "li#list_item_2")
Any tips on how to implement this would be great.
Thanks,
Adam
Edit: if I had selenium.get_element that would take a selector and return what it was, I could then perform the assertion in the next step.
i.e.
element = selenium.get_element("css=li:nth-child(1)")
assert_equal(element, "li#list_item_2")
(I think).
Your example won't work because you're comparing two strings that aren't equal. One way to assert that your element has moved would be to use isElementPreset as demonstrated below:
//before drag and drop
assertTrue(selenium.isElementPresent("css=#source li:nth-child(1)"));
assertFalse(selenium.isElementPresent("css=#target li:nth-child(1)"));
//drag and drop code here
...
//after drag and drop
assertTrue(selenium.isElementPresent("css=#target li:nth-child(1)"));
assertFalse(selenium.isElementPresent("css=#source li:nth-child(1)"));
This example uses the Java client API, but it should be easy to work out how to do it in your preferred client API. It will also depend heavily on your application, as the above will check that the element with id of 'target' has one child li element before the drag and drop, and none afterwards. If you have a snippet of your HTML source I might be able to prove a more robust example.