Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jasleow's avatar

Testing Local vs Remote (Live) Site

I'm new to testing. I am using phpunit to test my Laravel project locally:

        $this->visit('/landing')
            ->click('Sign In With Email')
            ->see('Login Existing User')
            ->type('test@example.com', 'email')
            ->type('testpassword', 'password')
            ->press('Login')
            ;

MY QUESTION IS:

How do I reproduce this test on the live server? (Can I run a live test from my local machine?)

What I've tried (and failed):

$this->visit('http://mysite.com/landing');   
// didn't work as it won't go to external links

$client = new GuzzleHttp\Client();
$response = $client->get('http://mysite.com/landing');
$body = $response->getBody(); 
// Goes to external links but I can't access 
// the ->click() ->see() ->press() methods this way

Why This is a problem:

My local machine has homestead so works beautifully. My remote (live deployment) server has some configurations out of my control which cause various API's and functions to break.

Sorry if this is a really basic question.

0 likes
10 replies
bobbybouwmann's avatar

Not sure why you want to go to the page of your live site. That's not what testing is for. You can run the tests locally, if that works fine you can be sure that it works on a live environment as well (at least if your local machine is the same as the server). With Homestead you always have the same setup as a Forge server ;) So if it works in Homestead, it works on Forge :D

2 likes
jasleow's avatar

Thank you. I need to test the live site because I don't have a Forge server and the live site is on shared hosting. The shared hosting had a lot of errors because of server configuration and modsec rules. I had to fix the errors manually which only came out during (I'm new to testing and I guess you would call it) User Testing.. It was terrible. All the tests worked locally but live deployed site broke in several places and the test users found the errors manually. That was pretty embarrassing.

I will look into getting maybe a Forge site later thank you.

(I don't know the formal name for the testing that I've coded above).

In the meantime, how would I reproduce the above testing on live site, if I needed to?

ifpingram's avatar

@jasleow as you have found out, you can't reliably reproduce it, as the configurations are different - testing only really works when all the different environments are in sync with each other configuration wise. You only really have two options:

1 - Pain and suffering; debugging the existing production server and configuring it so the tests work

2 - Ease and happiness; moving the site to a Laravel Forge instance.

I would save yourself further embarrassment and look to migrate ASAP.

Good luck!

1 like
MikeHopley's avatar

You only really have two options:

Not true. You can run your tests on a remote server as well.

I strongly recommend that you don't run tests on the live site. It seems like a great idea, but it will bite you -- databases getting overwritten, that sort of thing!

Instead, you can set up a copy of your site for testing. For example, testing.domain.com. You can run all your "normal" tests from the server's command line (using SSH to access the server).

You can even run Webdriver acceptance tests against the server. It's a bit fiddly to set up, as you need to arrange MySql tunnelling.

Of course, this assumes that you have SSH access on your shared hosting. If you don't, well...maybe you have bigger problems. :/

With all that said, Forge may be the easier/better option, providing you're happy with the limitations/cost that it imposes.

1 like
jasleow's avatar

@MikeHopley - THANK you for the lateral thinking (server command line SSH and WebDriver). Amazing recommendations. I think that will be my accepted answer (while I @ifpingram look into getting budget approval for Forge - which will take months.) Just a clarification:

Webdriver acceptance tests against the server: I think this is what I need to do.

I searched just now and found your thread, which I'll try my best to understand.

Should I get Codeception? Selenium? I'm only using phpunit now. Is the method in that thread still the best way? Thanks so much.

MikeHopley's avatar

First, about Forge: I'm not using it personally, as I use a different server-managing service (which I feel offers better security). But I would seriously consider Forge, as it's very popular in the Laravel community. The Forge + Envoyer combination also looks pretty slick.

Personally I have four different test suites. I am practical about these things, so I've basically organised them into a combination of "types" but also speed:

  • Unit (very fast)
  • Functional (quite fast)
  • External (slow)
  • Browser (very slow)

My unit tests are not super-strict. I allow them to do things like access the file system to load some testing data. They are still extremely fast.

My "functional" tests include tests that hit the database, but also the kind of acceptance test like your example (using Laravel's testing tools). You could argue that these do not belong in this suite, because they are acceptance tests, but I'm more concerned about practicality than taxonomy. They are slightly slower, but still fast enough to run the individual test on saving the related class.

My external tests are for testing external API integration, that sort of thing. Quite slow, but I don't often need to run them. I do not run these on save.

My "browser" tests are the ones using Webdriver. These acceptance tests are much slower, but they have one crucial advantage: because they are in a real browser, javascript will be executed. So I only use these when the interactions involve javascript.

This is just an example of what works for me. You can organise your tests differently according to what makes sense for you or your team.

I am using Codeception. There are other options. The "browser" tests are the ones that cause the most hassle getting everything set up correctly. You need to install (and run) Selenium Webdriver. You need to set up a database dump to be run and reset for each test. This makes the tests really slow when run against a remote server over an SSH tunnel, because all the MySql commands are slowed down hugely, making the "start up" time very long. Thankfully that type of testing is needed only very occasionally, maybe before a significant update to the live site.

I have found Firefox the best browser for working with Webdriver.

I would not bother even setting up Codeception unless you have a need to test javascript interactions. It's very powerful, but it's also quite a big hassle. The testing tools out-the-box with Laravel 5 cover almost all your needs.

1 like
jasleow's avatar

This is a record of what I did to get external testing working without needing a Forge server, so that others can learn and in case I forget. @MikeHopley Thanks for your explanation it really helped me get some clarity on the different types of testing. If you could lend some insight on step 7 below it would be great. My first time doing an external test so I really needed and appreciated your help! I really appreciated your practical approach to testing instead of strict taxonomy - working in the real world isn't always textbook and requires lateral thinking. Kudos!

How to test external web addresses with phpunit

(For: live testing, deployment servers, different domain test, web site

Mac OSX, Laravel 5.1

  1. Install Jeffrey's Laracasts/Integrated package (not specifying dev-master gave me errors). I pulled in dev-master 4dad96a (Oct 22, 2015).

Caveat: Laracasts Integrated works great for Selenium (browser based) testing to any url in Laravel 5.1, but doesn't seem to work for me for normal unit testing (also in Laravel version 5.1).

composer require laracasts/integrated dev-master --dev
  1. Set up the selenium test case as specified in the Laracasts Selenium Video.
use Laracasts\Integrated\Services\Laravel\Application as Laravel;
use Laracasts\Integrated\Extensions\Selenium;
use Laracasts\Integrated\Services\Laravel\DatabaseTransactions;
use Laracasts\TestDummy\Factory as TestDummy;

class SeleniumTest extends Selenium
{
    use DatabaseTransactions;      // Ensure that any transactions created here are rolled back after the test.
    use Laravel;

    protected $baseUrl = "https://external.site.com"; 
    // This changes the site domain but it 
    // requires Laravel & Laracasts Integrated & Selenium 

    /** @test */
    function go_to_external_site()
    {
    // N.B. That @test comment is important 
        $this->visit('/')
            ->see('Welcome to external.site.com')
            ->see('Login')
            ;
    }

    /** @test */
    function go_google()
    {
        $this->visit('https://google.com.au')
            ->see('Google')
            ->wait(2000);
    }
  1. Install Selenium from here - go to downloads and get standalone version.

  2. Install Firefox because Selenium defaults to Firefox

  3. Run selenium server (it prompted me to download Java SDK which I did - version 8u74)

java -jar selenium-server-standalone-2.52.0.jar 
  1. run phpunit normally - It should open Firefox and visit your external site - success!

  2. Set up MySQL Tunnelling - ??

Step 7 is the next step that I haven't got to yet. @MikeHopley suggests (thanks to his post below):

plink -L 3306:127.0.0.1:3306 username@domain.com
    // where "username@domain.com" is your SSH login.
2 likes
MikeHopley's avatar

Actually I'd forgotten that Laracasts Integrated includes a Selenium driver. I would like to try that instead of Codeception, because that would give me one unified, elegant API for writing my acceptance tests. As it stands, the Codeception API is different from Integrated.

(But I'm not going to do it now, because it would be spending time I don't really have.)

The MySql tunnelling is a bit of a pain to set up. But before you do this, I would suggest getting your Selenium-based tests to run locally. Have you done that?

Anyway, for the MySql tunnelling, I just kept looking for guides on the web and fiddling until it worked. :/ I am on Windows so I ended up using Plink. For what it's worth, the command that worked for me was this:

plink -L 3306:127.0.0.1:3306 username@domain.com

...where "username@domain.com" is your SSH login.

1 like
jasleow's avatar

@MikeHopley Thanks for your awesome help. Yes I got it working locally. I'll look into plink. I updated the steps above as well to mention it.

Caveat re: Laracasts Integrated and Selenium as unified API - Just so you don't waste time (like I did) trying to get this unified: Laracasts Integrated can't (as far as I know) replace the built in Laravel testing, at least not in 5.1.

I'm using Laracasts Integrated to run Selenium based tests locally (and I discovered Selenium thanks to you). Its great.

But Laracasts Integrated clashes with the Laravel's built in testing in 5.1 - when using Laracasts Integrated to do non-selenium unit testing it throws an error and refuses to test - something about the protected method within one of the vendor files needs to be public (or vice versa)... Whereas using Integrated to do Selenium testing is fine / amazing.

I haven't looked deep into fixing it because I'm not confident enough to change the vendor code. There's an issue raised for this error but it is not scheduled for a fix as far as I know.

The Laravel implementation and the Laracasts Integrated implementation are both still excellent and elegant. But its not one unified elegant API.

In summary, you might find the same outcome as me if you look to migrate from Codeception: I need Laravel built in testing for the unit testing, and I need Laracasts Integrated for the Selenium based testing.

1 like
MikeHopley's avatar

Thanks for the heads-up! I'll stick with what I've got.

Please or to participate in this conversation.