vendredi 27 mars 2020

python; monkeypatch in pytest setup_module

My question is similar to but is not a duplicate of: How to use monkeypatch in a "setup" method for unit tests using pytest?. That OP is not using pytest setup_module

So pytest provides setup_module and teardown_module (doc: https://docs.pytest.org/en/latest/xunit_setup.html#module-level-setup-teardown). However, they don't seem to take pytest fixtures.

I have to monkeypatch an object for multiple tests; it has to be patched, "started", then used in a bunch of tests, then stopped. It is not really a use case for fixtures since it's a multithreaded application and we are testing against the running application.

Right now, I am doing a series of tests that cannot be run in parallel because all are dependent on the first test, in effort to hackaround setup_module:

def test_1_must_come_first(monkeypatch, somefixture...):
    # patch my thing
    monkeypatch.setattr("mything.init_func", somefixture)
    mything.start()

def test_2()
    # use mything

def test_3()
    # use mything

...

def teardown_module():
    mything.stop()    

What I would like instead is to move the patching in the first step so that the tests themselves can be run in parallel and not dependent:

def setup_module(monkeypatch, somefixture):
    monkeypatch.setattr("mything.init_func", somefixture)
    mything.start()

def test_1():
    # use mything

def test_2()
    # use mything

# NO LONGER AN ORDERING DEPENDENCY AMONG TESTS
...

def teardown_module():
    mything.stop()

Is there a way to achieve this?

Is it bad practice to use the DTOs of the system under test in the actual test?

I am creating some "black-box" functional tests for a Java/Spring web application that has many DTOs, some are quite complex. When it comes to create the JSON body for the test HTTP requests, it would save me a lot of time if I were to use the existing DTOs, however doesn't it defeat the "black-box" part? If I'm not supposed to use them, what is the simplest approach?

Thank you for your attention.

Library testing strategy with communications

thank you for reading!

I have developed Java Integration SDK for communication with a REST API endpoint. I would like to get advise on testing strategy and execution.

Should the integration sdk and rest server be deployed in dockers and then client executing test calls, or test should to to running dev server? Or I should make a custom endpoint?

Are there any standard REST integration testing protocols?

Any advice on how to simulate timeout, latency, not reachable endpoint and retries?

Happy Friday guys!

Testing PUT method in Django Rest Framework

I'm trying to test a PUT method in django rest framework. I get HttpResponsePermanentRedirect instead of response object. My views for a put method are set to send status 200 after successful update.
Error:
self.assertEqual(response.data, serializer.data) AttributeError: 'HttpResponsePermanentRedirect' object has no attribute 'data'

tests.py

class PostTestGetAndPutMethod(APITestCase):
    def setup(self):
        Post.objects.create(title="POST CREATED", content="POST WAS CREATED")
        Post.objects.create(title="POST CREATED 2", content="POST WAS CREATED 2")
        Post.objects.create(title="POST CREATED 3", content="POST WAS CREATED 3")

    def test_get_posts(self):
        '''
        Ensure we can get list of posts
        '''
        # get API response 
        response = self.client.get(reverse('posts'))
        # get data from DB
        posts = Post.objects.all()
        # convert it to JSON
        serializer = PostSerializer(posts, many=True)
        # check the status 
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data, serializer.data)

    def test_update_put_post(self):
        '''
        Check if we can update post 
        '''
        data = {'title': 'POST MODIFIED', 'content': 'CONTENT MODIFIED'}
        response = self.client.put('/posts/1', data)
        serializer = PostSerializer(data)
        self.assertEqual(response.data, serializer.data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

views.py

@api_view(['GET', 'PUT', 'DELETE'])
def post_detail(request, pk):
    """
    Retrieve, update or delete a code snippet.
    """
    try:
        post = Post.objects.get(pk=pk)
    except Post.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = PostSerializer(post)
        return Response(data=serializer.data, status=status.HTTP_200_OK)

    elif request.method == 'PUT':
        serializer = PostSerializer(post, data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        post.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

TestNG eclipse plugin

I am using TestNG eclipse plugin to execute test cases. I need to group @Test methods and apply testng.xml file together. But plugin allows only one as shown radio button in screenshot. Is there any way to apply Group and Suits together?

Whole purpose to do is to apply groups and allow-return-values="true" in test methods.

enter image description here

Laravel: Assert Email verification is sent with mail:fake() in a test

I'm making an SPA and using Laravel for the API. This requires making my own authentication structure. I've borrowed from Laravel's auth and I'm making it work for my REST API.

I have a registration test and I've added assertions to test if the email verification email gets sent to the user that just registered.

The docs explain you can fake email sends and assert that specific ones get sent: https://laravel.com/docs/6.x/mocking#mail-fake

I'm having trouble finding how I can assert that the email verification specifically was sent.

    /**
     * @test
     */
    public function a_user_can_register_and_receives_verification_email()
    {


        Mail::fake();

        $response = $this->json( 'POST', '/api/register', [
            'first_name' => 'User',
            'last_name' => 'Example',
            'email' => 'user@example.com',
            'password' => 'password'
        ])->assertStatus(201);

        $user = $response->getData();

        $this->assertDatabaseHas('users', [
            'email' => $user->email
        ]);

        // Assert a message was sent to the given users...
        Mail::assertSent(MailMessage::class, function ($mail) use ($user) {
            return $mail->hasTo($user->email);
        });


    }

I was trying to hunt down what sendEmailVerificationNotification() does, and it let me to Illuminate\Auth\Notifications\Verify

It is a little confusing to me, but seems to be sending a MailMessage, which is what I'm asserting. However, my test fails: The expected [Illuminate\Notifications\Messages\MailMessage] mailable was not sent

This is my register method on my controller:

    public function register(Request $request) {

        $request->validate([
            'first_name' => ['required', 'string', 'max:255'],
            'last_name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8'],
        ]);

        $user = User::create([
            'first_name' => $request->first_name,
            'last_name' => $request->last_name,
            'email' => $request->email,
            'password' => Hash::make($request->password)
        ]);

        event(new Registered($user));

        return $user;

    }

api routes

Route::post('register', 'Auth\RegisterController@register');
Route::get('email/resend', 'Auth\VerificationController@resend')
    ->name('verification.resend');

Route::get('email/verify/{id}/{hash}', 'Auth\VerificationController@verify')
    ->name('verification.verify');

If I hit my register route via Postman, the email does get sent with the appropriate link. I just cant pass the test to verify.

JavaScript xPath command does not run co-mingled with Selenium Java program on every run

The below javascript (co-mingled with Java in Selenium) does not run xpath command successfully on every run. However my Java command runs successfully, it's the xpath that I'm having issues with. (In other words, sometimes xpath command runs successfully and at other times it does not). I changes jdk from 13 to jdk8, and that didn't work. I don't know what's needed.

I'm new with learning automation testing and I'm teaching myself.

Here's the command line:

driver.findElement(By.xpath("//button[@type='button' and @data-test-id='checkbox']")).click();

Error response:

JavaScript error: , line 0: NotAllowedError: The play method is not
allowed by the user agent or the platform in the current context,
possibly because the user denied permission.
Exception in thread "main"
org.openqa.selenium.StaleElementReferenceException: The element
reference of <button class="c27KHO0_n b_0 M_0 i_0 I_T y_Z2uhb3X
A_6EqO r_P C_q cvhIH6_T ir3_1JO2M7 P_0" type="button"> is stale;
either the element is no longer attached to the DOM, it is not
in the current frame context, or the document has been refreshed