What's wrong with this code? - the check is not happening

I’m trying to make this work:

`

object Login {

val sequence =
feed( Config.USER_FEED )
.group( “Login” ) {
.exec()
.expect_302_REDIRECT_TO( LOGIN_URL,
http( “1) Main URL” )
.get( Path.root )
)
.expect_200_OK(
http( “2) Login Page” )
.get( $(LOGIN_URL) )
.check( css( “”“input[name=“session”]”"", “value” ).saveAs( SESSION_ID ) )
)
.expect_302_REDIRECT(
http( “3) Submit Credentials” )
.post( $(LOGIN_URL) )
.headers( Headers.formPost )
.formParam( “session”, $(SESSION_ID) )
.formParam( “username”, $(USER_NAME) )
.formParam( “password”, $(PASSWORD) )
.formParam( “action”, “Login” )
)

`

Here’s what I’m doing to implement it:

`
object SessionConstant {

def $( s : String ) = { “${” + s + “}” }

// debug
val REQUEST_URI = “REQUEST_URI”
val RESPONSE_STATUS = “RESPONSE_STATUS”
val RESPONSE_BODY = “RESPONSE_BODY”

// Redirect
val REDIRECT_TO = “REDIRECT_TO”
// …
}
`

`
import io.gatling.core.Predef._
import io.gatling.core.structure.ChainBuilder
import io.gatling.http.Predef._
import io.gatling.http.request.builder.HttpRequestBuilder
import io.gatling.http.request.builder.HttpRequestWithParamsBuilder

import SessionConstant._

object Expect {

def debugExtracts ( request : Any ) =
if ( request.isInstanceOf[HttpRequestBuilder] ) request.asInstanceOf[HttpRequestBuilder]
else request.asInstanceOf[HttpRequestWithParamsBuilder]
.check( status.saveAs( RESPONSE_STATUS ) )
.check( header(“Location”).optional.saveAs( REDIRECT_TO ) )
.check( currentLocation.saveAs( REQUEST_URI ) )
.check( bodyString.saveAs( RESPONSE_BODY ) )

implicit class ChainBuilderExtensions ( val c : ChainBuilder ) {

def expect_200_OK ( request : Any ) =
c.exec( debugExtracts( request ).check( status.is( 200 ) ) )
.doIf( session => session( RESPONSE_STATUS ).as[Int] != 200 ) { exec( DEBUG.lastRequest _ ) }
.exitHereIfFailed

def expect_302_REDIRECT ( request : Any ) =
c.exec( debugExtracts( request ).check( status.is( 302 ) ) )
.doIf( session => session( RESPONSE_STATUS ).as[Int] != 302 ) { exec( DEBUG.lastRequest _ ) }
.exitHereIfFailed

def expect_302_REDIRECT_TO ( name : String, request : Any ) =
expect_302_REDIRECT( request )
.exec( session => session.set( name, session( REDIRECT_TO ) ) )

}
}
`

It compiles and runs. But when it gets to the .doIf() block it complains that RESPONSE_STATUS does not exist, implying that debugExtracts() did not properly add the check to save the status. Any thoughts as to why it is not working? Or suggestions on the “right” way of doing this?

Thanks!

Easy.

Let’s add some parens:
def debugExtracts ( request : Any ) =
if ( request.isInstanceOf[HttpRequestBuilder] ) {
request.asInstanceOf[HttpRequestBuilder]
} else {
request.asInstanceOf[HttpRequestWithParamsBuilder]
.check( status.saveAs( RESPONSE_STATUS ) )
.check( header(“Location”).optional.saveAs( REDIRECT_TO ) )
.check( currentLocation.saveAs( REQUEST_URI ) )
.check( bodyString.saveAs( RESPONSE_BODY ) )

}

So you’re only saving response status when performing a POST.

That doesn’t give me what I want.

The purpose is to save it for all requests, because sometimes the environments may be unstable and give random errors, or when I switch from one environment to another it may not work properly. I want it to dump out the details of the failed request every time, whether it is a post or a get. That way I can tell right away what happened.

Yeah, it doesn’t give you what you want, that was exactly my point!
I just made parens explicit but I didn’t change the logic of what you wrote, it’s exactly the same.

So, what I am TRYING to do is along the lines of:

( if isGet ? request.asGet : request.asPost ).chain…

When I try adding parens around the if/else I get a compile error: “value check is not a member of _1”

Is there a way in Scala to do what I am trying to do, or do I have to duplicate my checks, once for each class type?

Okay, I give up on trying to eliminate the duplication. I just created two versions of each method, one for each request type. Then it works. It feels like sacrilege, but what matters is that it works.

If you have a better idea how to do it, I’m all ears! :slight_smile:

Generics

def debugExtracts[T <: AbstractHttpRequestBuilder[T]](req: T) : T =
req.check( status.saveAs( RESPONSE_STATUS ) )
.check( header(“Location”).optional.saveAs( REDIRECT_TO ) )
.check( currentLocation.saveAs( REQUEST_URI ) )
.check( bodyString.saveAs( RESPONSE_BODY ) )

Ah, SO much better! Thank you! I appreciate you being willing to help us get up to speed in how to use Scala.

This is what I ended up with, which works like a charm:

`
import io.gatling.core.Predef._
import io.gatling.core.structure.ChainBuilder
import io.gatling.http.Predef._
import io.gatling.http.request.builder.AbstractHttpRequestBuilder

import SessionConstant._

object Expect {

implicit class ChainBuilderExpect ( val c : ChainBuilder ) {

def expect[T <: AbstractHttpRequestBuilder[T]] ( code: Int, request : T ) =
c.exec( request
.check( status.saveAs( RESPONSE_STATUS ) )
.check( header(“Location”).optional.saveAs( REDIRECT_TO ) )
.check( currentLocation.saveAs( REQUEST_URI ) )
.check( bodyString.saveAs( RESPONSE_BODY ) )
.check( status.is( code ) )
)
.doIf ( session => session( RESPONSE_STATUS ).as[Int] != code ) { exec( DEBUG.lastRequest _ ) }
.exitHereIfFailed

def expect_200_OK [T <: AbstractHttpRequestBuilder[T]] ( request : T ) = expect( 200, request )
def expect_302_REDIRECT [T <: AbstractHttpRequestBuilder[T]] ( request : T ) = expect( 302, request )
def expect_302_REDIRECT_TO [T <: AbstractHttpRequestBuilder[T]] ( name: String, request: T ) =
expect( 302, request )
.exec( session => session.set( name, session( REDIRECT_TO ).as[String] ) )

}
}
`

Beware, there’s an issue with your expect_302_REDIRECT_TO.
If for whatever reason you don’t end up with a 302, you won’t have a REDIRECT_TO so session( REDIRECT_TO ).as[String] will crash.
You should use asOption.

Wouldn’t the “.exitHereIfFailed” stop me from ever trying to execute the offending code in the event that there is not a 302?

If it was set before, yes :wink: