Is there a way to dynamically pass payload to my tests in pytest? - pytest

I want to the tests to get request body data dynamically
class TestPlaylistCreateView:
def test_create_playlist_with_valid_name(self, authorized_api_client):
url = reverse("create-playlist")
data = {
"name": name,
"is_public": "True"
} # <------- concrete payload
response = authorized_api_client.post(url, data)
assert response.status_code == status.HTTP_201_CREATED
def test_create_already_created_playlist(self, authorized_api_client, create_playlist):
url = reverse("create-playlist")
data = {
"name": create_playlist.name,
"is_public": create_playlist.is_public
} # <------- again the same payload
response = authorized_api_client.post(url, data)
assert response.status_code == status.HTTP_400_BAD_REQUEST
I would like to avoid repeating myself everytime I need request body data. is there a way to do it, maybe through a fixture or something.
my fixtures for the test
#pytest.fixture
def create_user():
return UserFactory()
#pytest.fixture
def authorized_api_client(create_user):
api_client = APIClient()
api_client.force_authenticate(user=create_user)
return api_client
#pytest.fixture
def create_playlist():
return PlaylistFactory()

Related

IllegalStateException thrown when reading the vert.x http client response body

I am getting the following error when I attempt to read the body from the http client response object. I don't get the exception all the time so I guess it's a threading issue related to the CompletableFuture. Any idea of what I am doing wrong? I use vert.x 3.8.1
java.lang.IllegalStateException
at io.vertx.core.http.impl.HttpClientResponseImpl.checkEnded(HttpClientResponseImpl.java:134)
at io.vertx.core.http.impl.HttpClientResponseImpl.endHandler(HttpClientResponseImpl.java:153)
at io.vertx.core.http.impl.HttpClientResponseImpl.bodyHandler(HttpClientResponseImpl.java:193)
at com.diagnostics.Response.body(Web.kt:116)
at com.diagnostics.Response.bodyNow(Web.kt:111)
at com.diagnostics.Response.bodyNow$default(Web.kt:110)
at com.diagnostics.Main.postVerificationTest(Main.kt:73)
at com.diagnostics.Main.main(Main.kt:52)
at com.diagnostics.Main.main(Main.kt)
Code that throws the exception:
val response = client.get(requestUri = "/api/info").get(3, TimeUnit.SECONDS)
val expectedStatus = 200
assertConditionOrExit(pvtLog, response.status == expectedStatus, "response status is ${response.status} expecting $expectedStatus")
val body = response.bodyNow()
assertConditionOrExit(pvtLog, body.isNotEmpty(), "body is empty expecting a non empty value")
The http client response object is created from the following code:
private fun request(
method: HttpMethod,
port: Int,
host: String,
requestUri: String
): CompletableFuture<Response> {
val future = CompletableFuture<Response>()
httpClient.request(method, port, host, requestUri)
.exceptionHandler { future.completeExceptionally(it) }
.handler { resp -> future.complete(Response(resp)) }
.end()
return future
}
And the body is retrieved...
fun bodyNow(timeout: Long = 10, unit: TimeUnit = SECONDS): String {
return body().get(30000, SECONDS)
}
fun body(): CompletableFuture<String> {
val future = CompletableFuture<String>()
resp.bodyHandler { buff -> future.complete(buff.toString())}
return future
}
The body() function sets a bodyHandler after the HttpClientRequest handler has been invoked in the request() method.
So there is a chance that, while your main thread proceeds, the eventloop receives content and drops it. If content is small, the request could even end before the bodyHandler is set.
This is why you only see the exception from time to time.
If you want to set the bodyHandler later, you must pause the HttpClientResponse:
httpClient.request(method, port, host, requestUri)
.exceptionHandler { future.completeExceptionally(it) }
.handler { resp ->
resp.pause() // Pause the response
future.complete(Response(resp))
}
.end()
Then resume it after setting the bodyHandler:
resp.bodyHandler { buff -> future.complete(buff.toString())}
resp.resume()

How to implement a message with a custom function code in pymodbus?

I'm currently trying to implement a modbus request that has a custom function code. The implementation is based on this example: custom_message.py
import struct
from pymodbus.pdu import ModbusRequest, ModbusResponse
from pymodbus.client.sync import ModbusTcpClient
client = ModbusTcpClient('192.168.0.55')
connection = client.connect()
class CustomModbusResponse(ModbusResponse):
# some fancy decoding should be done here..
pass
class CustomModbusRequest(ModbusRequest):
function_code = 55
def __init__(self, address):
ModbusRequest.__init__(self)
self.address = address
self.count = 1
def encode(self):
return struct.pack('>HH', self.address, self.count)
def decode(self, data):
self.address, self.count = struct.unpack('>HH', data)
def execute(self, context):
if not (1 <= self.count <= 0x7d0):
return self.doException(ModbusExceptions.IllegalValue)
if not context.validate(self.function_code, self.address, self.count):
return self.doException(ModbusExceptions.IllegalAddress)
values = context.getValues(self.function_code, self.address,
self.count)
return CustomModbusResponse(values)
request = CustomModbusRequest(0)
result = client.execute(request)
print(result)
The request works as expected. I can see the correct response on the network layer. However I can't parse the result. Pymodbus is throwing the following error:
DEBUG:pymodbus.factory:Factory Response[55]
ERROR:pymodbus.factory:Unable to decode response Modbus Error: Unknown response 55
ERROR:pymodbus.transaction:Modbus Error: [Input/Output] Unable to decode request
The example states that in this case, I would have to:
If you implement a new method that is not currently implemented, you
must register the request and response with a ClientDecoder factory.
Is there an elegant way to do this without patching the library?

Return from function in body and not only in last line in REST API Scala and play

I develop Rest API with scala and play framework.
In my product controller, I do validation of parameters received.
In case they fail from some reason, I would like to response with BadRequest in the middle of the function and not in the last line as scala works..
In the code below - Code continues running to the Ok line.. which is wrong, I want to return !
def getProduct(lang: String, t: String, ids: String) = Action {
val productIdsList = ids.split(",").toList
if (productIdsList.length.equals(1) && productIdsList(0).equals("")) //Validate input params are product Ids and not empty !
{
var errorResponse:ErrorResponse[String] = ErrorResponse(ErrorCode.GeneralError, "No products IDs", 500)
BadRequest(Json.toJson(errorResponse))//maybe return BadRequest(Json.toJson(errorResponse) ??
}
val results = productService.getProducts(GetProductsRequest(lang,t,productIdsList));
Ok(Json.toJson(results))
// TODO: handle error
}
If implemented as:
return BadRequest(...)
It reply with error:
"method getProduct has return statement; needs result type"
I Understand this is bad practice, so what is the best practice for quitting the function without finishing it (and not throwing exceptions..)
Just put an else branch, so there's nowhere to continue:
def getProduct(lang: String, t: String, ids: String) = Action {
val productIdsList = ids.split(",").toList
if (productIdsList.length.equals(1) && productIdsList(0).equals("")){ //Validate input params are product Ids and not empty !
var errorResponse:ErrorResponse[String] = ErrorResponse(ErrorCode.GeneralError, "No products IDs", 500)
BadRequest(Json.toJson(errorResponse))//maybe return BadRequest(Json.toJson(errorResponse) ??
}else{
val results = productService.getProducts(GetProductsRequest(lang,t,productIdsList));
Ok(Json.toJson(results))
// TODO: handle error
}
}

Trying to define Scalatra webservice with JSON parameters

I am trying to define a webservice, using Scalatra, where the parameters are passed in in the body, preferably as JSON, not having everything on the url, as I have it now.
So, I would like this test to pass, but the commented out code is what passes currently. The non-commented code isn't JSON, but I also am not certain how I would pass JSON for testing, as put requires an Iterable in the second parameter.
class WebAppSpec extends MutableScalatraSpec {
addServlet(classOf[WebApp], "/*")
"PUT /phaseupdate" should {
"return status 200" in {
//put("/phaseupdate/test1/address1/starting/10") {
put("/phaseupdate", Map("filename" -> "test1", "entryaddress" -> "address1","name" -> "starting","percentcomplete" -> "10")) {
status must_== 200
}
}
}
My current definition, which is wrong, is:
put("/phaseupdate/:filename/:entryaddress/:name/:percentcomplete") {
val filename = params("filename")
val entryaddress = params("entryaddress")
val name = params("name")
val percentcomplete = params("percentcomplete")
So how do I define my put service to just call it with PUT /phaseupdate and have the parameters in the body?
I am trying to limit what is going into the webserver access log, basically.
The solution is to do this:
put("/phaseupdate") {
val filename = if (params("filename").indexOf('.') > -1) params("filename").substring(0, params("filename").indexOf('.')) else params("filename")
val entryaddress = params("entryaddress")
val name = params("name")
val percentcomplete = params("percentcomplete")
Basically, params() can read in what was passed.
The specs2 test is, and if this is followed by the get it returns the correct information.
"PUT /phaseupdate" should {
"return status 200" in {
put("/phaseupdate", Map("filename" -> "test1", "entryaddress" -> "address1", "name" -> "starting", "percentcomplete" -> "10")) {
status must_== 200
}
}
}

Databinder dispatch: Get uncompressed content of a 403 response

I am using databinder dispatch for making HTTP requests which works nicely, as long as the web server returns a 404.
If the request fails, the web server returns a 403 status code and provides a detailed error message in the response body as XML.
How to read the xml body (regardless of the 403), e.g. how can I make dispatch ignore all 403 errors?
My code looks like this:
class HttpApiService(val apiAccount:ApiAccount) extends ApiService {
val http = new Http
override def baseUrl() = "http://ws.audioscrobbler.com/2.0"
def service(call:Call) : Response = {
val http = new Http
var req = url(baseUrl())
var params = call.getParameterMap(apiAccount)
var response: NodeSeq = Text("")
var request: Request = constructRequest(call, req, params)
// Here a StatusCode exception is thrown.
// Cannot use StatusCode case matching because of GZIP compression
http(request <> {response = _})
//returns the parsed xml response as NodeSeq
Response(response)
}
private def constructRequest(call: Call, req: Request, params: Map[String, String]): Request = {
val request: Request = call match {
case authCall: AuthenticatedCall =>
if (authCall.isWriteRequest) req <<< params else req <<? params
case _ => req <<? params
}
//Enable gzip compression
request.gzip
}
}
I believe something like this works:
val response: Either[String, xml.Elem] =
try {
Right(http(request <> { r => r }))
} catch {
case dispatch.StatusCode(403, contents) =>
Left(contents)
}
The error will be in Left. The success will be in Right. The error is a String that should contain the XML response you desire.
If you need more, I believe you can look at HttpExecutor.x, which should give you full control. It's been a while since I've used dispatch, though.
Also, I'd suggest using more val's and less var's.