nikoloz's avatar

How to test sort functionality with PhpUnit?

Hello, I'm new to testing, and I'm wondering how it 's possible to test the sort and search function?

public function byCountry(Request $request): View
	{
		$countries = Country::latest();

		if ($request->search)
		{
			$countries->where('name', 'like', '%' . $request->search . '%')
			->orWhere('name_geo', 'like', '%' . $request->search . '%');
		}

		$covidStatisticSum = [
			'confirmed' => Country::sum('confirmed'),
			'deaths'    => Country::sum('deaths'),
			'recovered' => Country::sum('recovered'),
		];

		$query = Country::query();
		if ($sort = $request->input('sort'))
		{
			$query->orderBy($request->input('name'), $sort);
		}

		return view('dashboard.by-country', ['covidStatisticSum' => $covidStatisticSum, 'countries'  => $query->get()]);
	}

0 likes
5 replies
laracoft's avatar

@nikoloz

I just wanted to share my experience about testing, which was quite a bumpy ride considering that I did not write tests for the longest time. Your question triggered familiar memories.

  1. Did you write the sort and search code? (No, actual sort and search is by SQL)
  2. Then why does it need to be tested?

I hope this can help you think about tests in a different way and maybe result in writing code in a different way. From what I can tell, you might be better off testing if search terms are properly "remembered" by your code, likewise for sort.

Going further, after they are remembered correctly, they will be sent off to SQL. I ask the 2 questions again. Who actually constructs the SQL? (It is eloquent), does it need to be tested? This would be a subjective yes and no. If you really want to test it, probably can be done by just extracting the SQL using ->toSql() and checking that your terms are there.

Because of this, you might be better off abstracting/removing $request and view() and move the search/sort terms construction into another (more testable) function

An example can be:

public function addSearchAndSort($query_builder, Array $search, Array $sort)
{
				return $query_builder;
}

Hope it helps.

3 likes
tisuchi's avatar
tisuchi
Best Answer
Level 70

@nikoloz You can try something like this-


  /** @test */
    public function it_can_be_searched_by_given_keyword()
    {
        // Arrange
        $country1 = Country::factory()->create([
            'name' => 'the keyword foo exists here'
        ]);        
        
        $country2 = Country::factory()->create([
            'name_geo' => 'the keyword foo exists in name_geo'
        ]);

        // DECOY
        Country::factory()->create([
            'name' => 'the keyword does not exists here'
        ]);

        // Act
        // Call Search URL
        $response = $this->get('/put-you-search-url-here?search=foo');

        // Assert
        $response->assertStatus(200);
        $response->assertSee('the keyword foo exists here');
        $response->assertSee('the keyword foo exists in name_geo');
        $response->assertDontSee('the keyword does not exists here');
    }

Note: Make sure, you call the righ url in $this->get('/put-you-search-url-here?search=foo');.

5 likes
nikoloz's avatar

@tisuchi Thanks , test passed but when i check with --coverage test did not cover any line , why? i think it should be cover search functionality

3 likes
nikoloz's avatar

@tisuchi It was my mistake, I did not enter the user in the system before the test, your code worked for me thank you

5 likes

Please or to participate in this conversation.