How do you run behave (with python code) steps implementation with gherkin scenarios data input? - python-behave

I start python and TDD, I would like to know how to run behave steps with python and scenarios table for the two scenarios below:
The program ask a user to enter data (humididity level and temperature) and it prints those data.
For the first scenario, user fill out data and the program prints those data (normal case). I just want to check if there is data input
For the second scenario, if user fill out "text" the program return a syntax error.I would like to check the data type in #then steps
The problem is that when I run steps with behave command it asks me to enter data but I want the program uses data table in gherkin scenarios. Can you help please?
gherkin scenario below:
Feature: As a user I want fill out humidex data to visualize it
Scenario: user fill out humidex data correctly
Given a user
When user fill out humidexdata
|humidity|temperature|
|50% |28C° |
Then user visualize
|humidity|temperature|
|50% |28C° |
Scenario: user fill out humidex data with text
Given a user
When user fill out humidexdata
|humidity |temperature|
|lorem ipsum|lorem ipsum|
Then user visualize a syntax error "data syntax is wrong retry"
step implementations with behave:
from behave import *
from fillouthumidexdata import *
#given(u'a user')
def step_impl(context):
context.user = User()
#when(u'user fill out humidexdata')
def step_impl(context):
context.user.fillout_humidexData()
#then(u'user visualize')
def step_impl(context):
context.user.visualize_humidexData()
python code:
class User():
def __init__(self):
self.humidity = []
self.temperature =[]
def fillout_humidexData(self):
print("Enter humidity level (%)")
input(self.humidity)
print("Enter temperature (C°)")
input(self.temperature)
def visualize_humidexData(self):
print(self.humidity)
print(self.temperature)

I am not sure why you need actually separate User class as all of that can be done in simple steps, but following this approach I would change first a bit the User class at least to:
class User():
def __init__(self):
self.humidity = 0
self.temperature = 0
def fillout_humidexData(self, humidity, temperature):
self.humidity = humidity
self.temperature = temperature
def visualize_humidexData(self):
print(f'humidity: {self.humidity}')
print(f'temperature: {self.temperature}')
And then use the following steps:
from behave import step, given, when, then
from fillouthumidexdata import *
#given(u'a user')
def step_impl(context):
context.user = User()
#when(u'user fill out humidexdata')
def step_impl(context):
humidity, temperature = context.table.rows[0]
context.user.fillout_humidexData(humidity, temperature)
#then(u'user visualize')
def step_impl(context):
context.user.visualize_humidexData()
rows[0] should give you values from first row in your setup table(2 values from 2 columns).
I think this should work, but I am not sure if this is what you want.

Related

Change filepath of an image using command

I have written some code which takes a date of birth and calculates the correct Chinese horoscope animal (rat, dog etc.). I would like to add a gui whereby, when the user hits calculate, the gui shows a photo of the appropriate animal. To do that I think I have to make the file path for an image change within the command definition, but can't find a way to do this. I have simplified the code as far as possible below:
x = Tk()
x.state('zoomed')
def find_animal():
animal = 'tiger' # I've left out the actual calculation part
picture.place(relx=0.4, rely=0.5)
b = Button(x, text='Calculate', command=find_animal)
b.place(relx=0.5, rely=0.3)
file_path = 'rabbit.png'
pic = PhotoImage(file=file_path)
picture = Label(x, image=pic)
x.mainloop()
The thing I'm hoping to do is somehow alter the file_path variable within the find_animal function so that the image displayed changes from rabbit to tiger
You can use pic.config() to change the image path inside find_animal():
def find_animal():
animal = 'tiger' # I've left out the actual calculation part
pic.config(file=animal+".png")
picture.place(relx=0.4, rely=0.5)

Get ardupilot output channels

How do we get output channel values of an ardupilot from dronekit-python?
We can get input channels from vehicle.channels but I couldn't find anything similar for output channels.
EDIT:
from time import sleep
from dronekit import connect
import dronekit_sitl
sitl = dronekit_sitl.start_default()
connection_string = sitl.connection_string()
vehicle = connect(connection_string,wait_ready=True)
while not vehicle.is_armable:
sleep(1)
print"Initializing"
vehicle.armed = True
while not vehicle.armed:
print "Arming"
sleep(1)
print "Armed"
#vehicle.on_attribute('ch1out')
def ch1out_listener(self, name, msg):
print '%s attribute is: %s' % (name, msg)
for i in range(1000,2000,100):
vehicle.channels.overrides['3']=i
sleep(1)
vehicle.close()
It should print ch1out everytime I update channel 3 but it is not.
I assume what you mean output channels is this 'ch1out','ch2out' value and so on.
To get that value you can simply just using an attribute listener like this
#vehicle.on_attribute('ch1out')
def ch1out_listener(self, name, msg):
print '%s attribute is: %s' % (name, msg)
This function essentially just print the 'ch1out' value everytime it changes, you can just modify it accordingly. You can read more about this at here Observing attribute changes.
But if you want to access the output channel value directly from the vehicle object like the input channel or other attribute.
(Ex: vehicle.channels, vehicle.mode)
You can add the output channel to the vehicle object by following this example provided by the Dronekit-Python documentation Create Attribute in App.
The way to do this is to create a new vehicle class. You can do this following the example given in dronekit.
Then connect using your new class:
vehicle = connect(connection_string, wait_ready=True,
vehicle_class=MyVehicle) def raw_servo_callback(self, attr_name,
value):
print(value)
vehicle.add_attribute_listener('raw_servo', raw_servo_callback)
Here is the class for the above example:
from dronekit import Vehicle
class RawSERVO(object):
"""
:param ch1out: servo1
:param ch3out: servo3
"""
def __init__(self, ch1out=None, ch3out=None):
"""
RawIMU object constructor.
"""
self.ch1out = ch1out
self.ch3out = ch3out
def __str__(self):
"""
String representation used to print
"""
return "{},{}".format(self.ch1out, self.ch3out)
class MyVehicle(Vehicle):
def __init__(self, *args):
super(MyVehicle, self).__init__(*args)
# Create an Vehicle.raw_servo object with initial values set to None.
self._raw_servo = RawSERVO()
# Create a message listener using the decorator.
#self.on_message('SERVO_OUTPUT_RAW')
def listener(self, name, message):
"""
The listener is called for messages that contain the string specified in the decorator,
passing the vehicle, message name, and the message.
The listener writes the message to the (newly attached) ``vehicle.raw_servo`` object
and notifies observers.
"""
self._raw_servo.ch1out=message.servo1_raw
self._raw_servo.ch3out=message.servo3_raw
# Notify all observers of new message (with new value)
# Note that argument `cache=False` by default so listeners
# are updated with every new message
self.notify_attribute_listeners('raw_servo', self._raw_servo)
#property
def raw_servo(self):
return self._raw_servo
This is the solution if you are using PixHawk and Raspberry Pi connected through UART Issue source. You can configure this one using Mission Planner.
Output Channels read to none when both Serial1 and Serial2 Protocols are set to 2. I set both protocols to 1 and I set my Serial 1 baud to 57 and Serial 2 baud to 921. Had the UART connected through Telem 2.
Hope it helps!

Transfer Property ids (Array) to other TestCases in SoapUI/Groovy

I have an API to get list of ids, name, data etc. (TestCase name GET-APIs_OrderdByID_ASC)
I want to transfer those IDs to other following TestCases in same TestSuite or other TestSuite.
In SOAPUI, Property Transfer works within TestSteps in same TestCase. (Using OpenSource version). I need to transfer the property value among different TestCases / TestSuites.
Below is the code that I can extract ids from one testCase and also name of testCases/testSteps where I want to transfer.
import com.eviware.soapui.impl.wsdl.teststeps.*
import com.eviware.soapui.support.types.StringToStringMap
import groovy.json.*
def project = context.testCase.testSuite.project
def TestSuite = project.getTestSuiteByName("APIs")
def TestCase = TestSuite.getTestCaseList()
def TestStep = TestCase.testStepList
def request = testRunner.testCase.getTestStepByName("List_of_APIs_OrderByID_ASC")
def response = request.getPropertyValue("Response")
def JsonSlurperResponse = new JsonSlurper().parseText(response)
def Steps = TestStep.drop(3)
log.info JsonSlurperResponse.data.id
def id = JsonSlurperResponse.data.id
Steps.each {
it.getAt(0).setPropertyValue("apiId", id.toString())
log.info it.getAt(0).name
}
If I run above code, all the array values of id [1, 2, 10, 11, 12, 13, 14, 15, 16, 17, 18] are set to each of the following testSteps
I looked some other SO questions
Property transfer in SOAPUI using groovy script
groovy-script-and-property-transfer-in-soapui
Can anyone help me out. :-)
I have done something with datasinks as Leminou suggests.
Datasinks are a good solution for this. In test A, create a datasink step to persist the values of interest. Then in the target step, use a data source step, which links to the file generated by the datasink earlier.
The data sink can be configured to append after each test or start afresh.
If you're struggling to tease out the values for the datasink, create a groovy step that returns the single value you want, then in the datasink step, invoke the groovy.
Sounds a little convoluted, but it works.
You can use project level properties or testSuiteLevel properties or testCase Properties.
This way you can achieve the same thing that you get from Property Transfer step but in a different way.
Write a groovy step in the source test case to setProperty(save values you want to use later)
testRunner.testCase.setPropertyValue("TCaseProp", "TestCase")
testRunner.testCase.testSuite.setPropertyValue("TSuiteProp","TestSuite")
testRunner.testCase.testSuite.project.setPropertyValue("ProjectLevel","ProjectLevelProperty")
"TCaseProp" is the name of the property. you can give any name
"TestCase" is the value you want to store. You can extract this value and use a variable
for example
def val="9000"
testRunner.testCase.setPropertyValue("TCaseProp", val)
You can use that property in other case of same suite. If you want to use across different suites you can define project level property
use the below syntax in target testcase request
${#Project#ProjectLevel}
${#TestCase#TCaseProp}
${#TestSuite#TCaseProp}
<convertCurrency>${#TestSuite#TCaseProp}</ssp:SystemUsername>
System will automatically replace the property value in above request
https://www.soapui.org/scripting-properties/tips-tricks.html <-- Helpful link which can explain in detail about property transfer
Well the following Script works.
Just to change as
Steps.each { s ->
id.each { i ->
s.getAt(0).setPropertyValue("apiId", i.toString())
}
}
Here id is a ArrayList type. So We can loop through the List.
PS: We can do the same using for loop.

SOPUI - How to Check in Data base?

I have Req1
after running Req1 some Response will Display
something like
<a:Description>AFGHANISTAN</a:Description>
<a:Id>243</a:Id>
:
:
It will Display all countries and IDs
I wanted to check this in DB,
How I can do this?
First get your values from response
def groovyUtils = com.eviware.soapui.support.GroovyUtils(context)
def holder = groovyUtils.getXmlHolder("TestStepName#Response")
def descriptionFromResponse = holder.getNodeValue("//a:Description")
Then create an Sql instance (import is groovy.sql.Sql) as ,
Sql sqlInstance = Sql.newInstance(dbUrl, dbUsername, dbPsswd, dbDriverClass)
//Url e.g., - jdbc:oracle:thin:#localhost:1521/XE
//driverClass e.g., - oracle.jdbc.OracleDriver
//dbUsername- username of the required db user dbPsswd- password of the required db user
// This is what I use for oracle 11g
def result = sqlInstance.firstRow("Select Description from CountryTable where id='243'")
// if multiple records, def result = sqlInstance.rows("Select Description from CountryTable where id='243'")
result.each {key, val ->
log.info key
log.info val
log.info val==descriptionFromResponse //true if the both matches
}
Hope you know how to structure the test cases. If not please go through the link
Create a test suite -> test case
add the test request step that you are talking about
add another jdbc test step and get the detail that you wanted to verify the result against step1
add a groovy step : this will have get the responses of above both steps and traverse thru the nodes and compare the values. If every thing is fine it is ok, otherwise fail the test. Here you need to write some code in order to do the same.
You should be able to get the responses( of the first two steps) in 3 rd step using below script
import groovy.xml.*
def getResponse = {stepName ->
def step = testRunner.testCase.getTestStepByName(stepName)
def response = new String(step.testRequest.messageExchange.response)
def xml = new XmlSlurper().parseText(response)
xml
}
//provide name of the test steps for below two lines
def step1Response = getResponse('STEP1_NAME')
def step2XResponse = getResponse('STEP2_NAME')
Now required element values needs to be extracted and compared for both step1Response, step2Response

wxPython: get data in variables from Google Spreadsheet and also from user, work with all variables, return results to user

I hope I didn't miss any topic that could answer my problem. I'm here now because I'm terribly frustrated and tired with the following task:
- I have a Spreasheet with Drive.Google with lots of data in it
- I would like to create an application with wxPython that would pull data from this spreeadsheet (in the most easy way possible)
- Would also like to get multiple data from a user who will access this application through a nice interface (panel aka window)
- The multiple data introduced by the user should be able to work with the data pulled out from the Spreasheet. For example to see if the data introduced by the user is in the Spreadsheet or not and also some other operations with the next data introduced by the user.
- Finally and most importantly show the results to the user (later I would also like to add some functions to save somehow the results)
I hope I managed to express clearly what I would like to do. Now I'm new to Google API's, Python adn wxPython, but I have experience with C++ , php, html .
I've spent 2 weeks now with discovering Drive.Google and learning Python and wxPython. I did follow all tuturials on these, made my notes, read tones of stackoverflow questions-answers, wiki.wxpython.org etc. I learn every single day and I can do now many things separately but to have all functions like I described above I just couldn't work out how to do. At least please orient me in the direction. Awfel lot of times I spend hours doing examples and getting nowhere. I have Python, wxPython extention, GoogleAppEngine Launcher and even pyCharm demo. Please be kind. This is my first question ever.
here's the mess I made so far combining relevant examples:
import wx
import gdata.docs
import gdata.docs.service
import gdata.spreadsheet.service
import re, os
class Form(wx.Panel):
def __init__(self, *args, **kwargs):
super(Form, self).__init__(*args, **kwargs)
self.createControls()
self.bindEvents()
self.doLayout()
self.spreasht()
def createControls(self):
self.logger = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_READONLY)
self.saveButton = wx.Button(self, label="Elvegzes")
self.nameLabel = wx.StaticText(self, label="type Name1:")
self.nameTextCtrl = wx.TextCtrl(self, value="type here")
self.name2Label = wx.StaticText(self, label="type Name2:")
self.name2TextCtrl = wx.TextCtrl(self, value="type here")
def bindEvents(self):
for control, event, handler in \
[(self.saveButton, wx.EVT_BUTTON, self.onSave),
(self.nameTextCtrl, wx.EVT_TEXT, self.onNameEntered),
(self.nameTextCtrl, wx.EVT_CHAR, self.onNameChanged)]:
control.Bind(event, handler)
def doLayout(self):
raise NotImplementedError
def spreadsht(self):
gd_client = gdata.spreadsheet.service.SpreadsheetsService()
gd_client.email = 'my email address'
gd_client.password = 'my password to it'
gd_client.source = 'payne.org-example-1'
gd_client.ProgrammaticLogin()
q = gdata.spreadsheet.service.DocumentQuery()
q['title'] = 'stationcenter'
q['title-exact'] = 'true'
feed = gd_client.GetSpreadsheetsFeed(query=q)
spreadsheet_id = feed.entry[0].id.text.rsplit('/',1)[1]
feed = gd_client.GetWorksheetsFeed(spreadsheet_id)
worksheet_id = feed.entry[0].id.text.rsplit('/',1)[1]
al1 = raw_input('Name1: ')
print al1
al2 = raw_input('Name2: ')
print al2
rows = gd_client.GetListFeed(spreadsheet_id, worksheet_id).entry
for row in rows:
for key in row.custom:
if al1 == row.custom[key].text:
print ' %s: %s' % (key, row.custom[key].text)
def onColorchanged(self, event):
self.__log('User wants color: %s'%self.colors[event.GetInt()])
def onReferrerEntered(self, event):
self.__log('User entered referrer: %s'%event.GetString())
def onSave(self,event):
self.__log('User clicked on button with id %d'%event.GetId())
def onNameEntered(self, event):
self.__log('User entered name: %s'%event.GetString())
def onNameChanged(self, event):
self.__log('User typed character: %d'%event.GetKeyCode())
event.Skip()
def onInsuranceChanged(self, event):
self.__log('User wants insurance: %s'%bool(event.Checked()))
# Helper method(s):
def __log(self, message):
''' Private method to append a string to the logger text
control. '''
self.logger.AppendText('%s\n'%message)
class FormWithSizer(Form):
def doLayout(self):
''' Layout the controls by means of sizers. '''
boxSizer = wx.BoxSizer(orient=wx.HORIZONTAL)
gridSizer = wx.FlexGridSizer(rows=5, cols=2, vgap=10, hgap=10)
# Prepare some reusable arguments for calling sizer.Add():
expandOption = dict(flag=wx.EXPAND)
noOptions = dict()
emptySpace = ((0, 0), noOptions)
# Add the controls to the sizers:
for control, options in \
[(self.nameLabel, noOptions),
(self.nameTextCtrl, expandOption),
(self.allomas2Label, noOptions),
(self.allomas2TextCtrl, expandOption),
emptySpace,
(self.saveButton, dict(flag=wx.ALIGN_CENTER))]:
gridSizer.Add(control, **options)
for control, options in \
[(gridSizer, dict(border=5, flag=wx.ALL)),
(self.logger, dict(border=5, flag=wx.ALL|wx.EXPAND,
proportion=1))]:
boxSizer.Add(control, **options)
self.SetSizerAndFit(boxSizer)
class FrameWithForms(wx.Frame):
def __init__(self, *args, **kwargs):
super(FrameWithForms, self).__init__(*args, **kwargs)
notebook = wx.Notebook(self)
form2 = FormWithSizer(notebook)
notebook.AddPage(form2, 'CALTH')
self.SetClientSize(notebook.GetBestSize())
if __name__ == '__main__':
app = wx.App(0)
frame = FrameWithForms(None, title='Relevant title˝')
frame.Show()
app.MainLoop()
THANK YOU AGAIN!!!!!!!!!!!
First, make sure you can download the data you want with just Python. Then create a wxPython GUI with a single button. In that button's handler, have it call the script that can download the data you want.
If that causes your GUI to become unresponsive, then you'll need to use a thread to do the downloading. I recommend the following articles if that's the case:
http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/
http://wiki.wxpython.org/LongRunningTasks
Okay, so now you have the data downloading appropriately. Now you add a grid widget or a listctrl / object list view widget. Pick one of those. I prefer object list view, which you can read about here. Then in your button handler you can call your downloader script or thread and when that's done, you can load the widget with that data. If you're using a thread, then the thread will have to call the next step (i.e. the widget loading bit).
Now you should have your data displayed. All that's left is making it look pretty and maybe putting the downloading part into a menu item.

Resources