How to test RPC of SOAP web services? - python

I am currently learning building a SOAP web services with django and spyne. I have successfully tested my model using unit test. However, when I tried to test all those #rpc functions, I have no luck there at all.
What I have tried in testing those #rpc functions:
1. Get dummy data in model database
2. Start a server at localhost:8000
3. Create a suds.Client object that can communicate with localhost:8000
4. Try to invoke #rpc functions from the suds.Client object, and test if the output matches what I expected.
However, when I run the test, I believe the test got blocked by the running server at localhost:8000 thus no test code can be run while the server is running.
I tried to make the server run on a different thread, but that messed up my test even more.
I have searched as much as I could online and found no materials that can answer this question.
TL;DR: how do you test #rpc functions using unit test?

I believe if you are using a service inside a test, that test should not be a unit test.
you might want to consider use factory_boy or mock, both of them are python modules to mock or fake a object, for instance, to fake a object to give a response to your rpc call.

Related

How to write a unit test code for functions which make API requests to web?

I am writing unit-test code with pytest for my python functions.
Those functions work with requests module that allows us to easily talk to the web servers.
The thing is that the web server to which the functions communicate don't return same value.
For example, the functions communicate to www.toolmarket.com to ask how much Tommy drill is. But sometimes, Tommy drill is not in the list of the web shop. In this case, My test code returns f.
How can I write test code for this kind of function of code?
Edit : added test code
def test_get_data():
assert Info(None, None, None).get_data("Tommy drill") == (
"id" : "KRG552100411"
)
I want to do test like above. Tommy drill is just one of items in the shop. But the thing is sometimes, the item disappears from the list. So test returns f
The above code snippet looks like unit testing. And, since you are using requests module in the actual code, it is better you MOCK the API calls while writing the unit-tests.
It doesn't make an API call from the test function because we use a python mock. With mock, we use #patch and specify python where we are actually making an API call so that it knows what to mock.
It is validating the code if it can process the response. As a reason why, we don't want to make an API call to an external service every time we do unit testing.
To summarise -
When you make the actual API call, you're not doing unit testing, that's more like integration testing
When you want to do unit testing, you're testing if your code can accept and process the expected API call response without actually making the call. You do this by using a mocking library (for example the 'responses' library, which injects mock responses to calls made by requests.
If this helps, I would be happy to help on Python Mocking of API requests too.

Django Hostname in Testing

I am wondering if there is a way to obtain the hostname of a Django application when running tests. That is, I would like the tests to pass both locally and when run at the staging server. Hence a need to know http://localhost:<port> vs. http://staging.example.com is needed because some tests query particular URLs.
I found answers on how to do it inside templates, but that does not help since there is no response object to check the hostname.
How can one find out the hostname outside the views/templates? Is it stored in Django settings somewhere?
Why do you need to know the hostname? Tests can run just fine without it, if you use the test client. You do not need to know anything about the system they're running on.
You can also mark tests with a tag and then have the CI system run the tests including that tag.
And finally there is the LiveServerTestCase:
LiveServerTestCase does basically the same as TransactionTestCase with one extra feature: it launches a live Django server in the background on setup, and shuts it down on teardown. This allows the use of automated test clients other than the Django dummy client such as, for example, the Selenium client, to execute a series of functional tests inside a browser and simulate a real user’s actions.
The live server listens on localhost and binds to port 0 which uses a free port assigned by the operating system. The server’s URL can be accessed with self.live_server_url during the tests.
Additional information from comments:
You can test if the URL of an image file is present in your response by testing for the MEDIA_URL:
self.assertContains(response, f'{settings.MEDIA_URL}/default-avatar.svg')
You can test for the existence of an upload in various ways, but the easiest one is to check if there's a file object associated with the FileField. It will throw ValueError if there is not.

Python requests as automated test in a Jenkins pipeline

I am relatively inexperienced in the field of Python. I am working with Python Requets and BeautifulSoup. The scripts I write with it are all executable.
Since I don't know anything about Pytest and Unittest, I tried to acquire this knowledge, but I just can't get any further.
I've seen in particular that Python Requests works over Mocks, but I have to say, I'm not sure this is the right way to write tests and include them in a Jenkins pipeline. The goal is to test different http requests of a website, either as a unit test or via Pytest.
What is your opinion?
Is that also possible with Python requests (integration) via mocks?
Do I have to use Pytest or Unittesting?
import requests
from requests.exceptions import HTTPError
import pytest
from bs4 import BeautifulSoup
import postpython
page = requests.get('http://google.de')
soup = BeautifulSoup(page.content, 'html.parser')
print(soup)
Taken from here:
You have two types of tests:
Integration - An integration test checks that components in your
application operate with each other i.e. as a whole end-to-end without any mocks.
Unit - A unit test checks a small
component in your application in isolation i.e. mocking all the dependencies for that.
Suppose you have application code that makes a request to an API.
You would use unit test to check whether in your application code a request to the API is called or not (without actually making the API request). You would mock the behavior of sending request and plant a fake response in your unit test. This is so that you can test your code in isolation of the API request/response.
But, if you wanted to actually call the API and get back a real response, then you would use integration tests. This allows you to test the application behavior as a whole.
In python, unittest and pytest are two of many available test runner libraries for writing and managing such tests.
If you wanted to mock the requests/response then check this out: How can I mock requests and the response?
From what I understand, you're looking to actually make the request in your Jenkins CI/CD pipeline to the server and see if you get a successful response. This falls into the category of Integration Testing so you wouldn't need to mock anything.
You can do integration tests with both unittest or pytest.
Here's an example with pytest:
import pytest
def test_get_request():
response = requests.get('http://google.de')
assert response.status_code == 200
To run this you can run this command line task in your jenkins pipeline:
pytest your_test_file.py
You can follow this tutorial for more info and introduction on PyTest here.

functional testing during development

I am not exposed to many of the testing framework, and wonder any recommendation on achieving the following (functional testing) during development phase. Intention is to test a web application functionality (language agnostic?) though the exposed http (REST/JSON RPC) interface.
My backend in NOT written in Python, but because of the easiness of using requests library, and creating Ad hoc http request, I simply construct http POST/GET request with appropriate cookie, payload etc and check the response to validate the server correctness.
It is little tedious to enable specific test cases (comment out / boolean flag ), and verify the results. Any framework to make this more pleasant during the development phase where frequent changes are the norm.
thanks.
Well your on the right track with requests you could tie that directly into nose or unittest or any of the common python testing frameworks that exist, bit of background requests was actually written for testing flask
Use nose to run your tests. In this case, you can declare base classes of your tests to be like this:
class SlowTestBase(BaseTestCase):
slow = True
And run it like nosetests --attr="slow", or to exclude them --attr="!slow". You can find more on nose documentation at https://nose.readthedocs.org/en/latest/

Testing a server using Python script

I want to do conformance testing of thttpd server. I need to use the python scripts to test it.
Can you please share a script to test the transmission and reception of data to the server?
Also, what kind of possible tests need to be performed? Are there any specific parameters to be tested?
This can be done simply using the builtin urllib
urllib.urlopen(yourserveraddress).read()
You can also do other things with urllib2 that allow you to test more functionality.
If you want some more intence tests then you might want to build a twisted reactor to test all your functionality.

Categories