SitePoint Sponsor |
|
User Tag List
Results 1 to 13 of 13
Thread: simpletest and website testing
-
Sep 1, 2008, 12:38 #1
- Join Date
- Dec 2007
- Posts
- 348
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
simpletest and website testing
Hi guys,
Got a question regarding simpletest (by lastcraft). I'm loving unit testing at the moment, it's really making my life easier when testing/debugging things
Anyway, so far I have only tested individual objects and the interaction of objects. Since ultimately all these objects are going to work together to interpret a user request, do some processing maybe and then output some HTML - can we unit test this whole procedure?
obviously individual model/view/controller/etc classes can be tested by themselves or interacting with each other, but say if you start at index.php how did you check that, say, your application has produced a table of results? Just search for that pattern in the resultant output with assertPattern? What if we wanted to check a large, complex page with many elements that might be generated by PHP?
-
Sep 1, 2008, 12:55 #2
- Join Date
- Oct 2006
- Location
- France, deep rural.
- Posts
- 6,869
- Mentioned
- 17 Post(s)
- Tagged
- 1 Thread(s)
SimpleTest contains a webtester, else look at Selenium. This allows you to test, and record and playback tests from the outside in (from the GUI), unlike unit tests which test from the inside out, if I have understood it correctly.
Anyhow, its equally revolutionary if you have never come across it.
-
Sep 1, 2008, 23:54 #3
- Join Date
- Dec 2007
- Posts
- 348
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Thanks for the Selenium link, I'll have a look at it.
Are there any web tutorials for unit testing website output? The simpletest site isn't bad but I'd like some more examples.
Like, if I submitted a form which was validated, updated a database and then wanted to access a page reflecting the database change by the form submission, how could I test each stage of this? If I submit a form then I get forwarded to the thank you page or whatever, I can't test the internal processes.
-
Sep 2, 2008, 04:58 #4
- Join Date
- Jun 2003
- Location
- Melbourne, Australia
- Posts
- 440
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
What about querying the database directly to see if the change you expected occurred?
In any case, you might gain some confidence from the forwarded page. If you've designed the app to forward to a specific page only on success, and you have elsewhere tested that it happens only on success, then surely the forwarding to that page is indicative of success?Zealotry is contingent upon 100 posts and addiction 200?
-
Sep 2, 2008, 05:14 #5
- Join Date
- Dec 2007
- Posts
- 348
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
-
Sep 2, 2008, 06:30 #6
- Join Date
- Sep 2003
- Location
- Glasgow
- Posts
- 1,690
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Yes
but you should only manipulate what you can reach out and touch. Don't try to "look under the bonnet". For example if I order a pizza, I just need to assertPizzaIsDelivered(). I don't need to know if it arrived by bicycle or by van or if the caterer's dough database is down by another pizza base.
OOP is all about encapsulating chunks of behaviour behind an interface and tests should respect this. It's very harmful if implementation details leak through since that makes code harder to refactor. Changes to low level classes will have a knock-on effect in higher level tests.
In each test you have a very specific point of view. In a unit test, this is the POV of clients of the tested class. These clients can only operate the public interface and so that's all you are allowed to do in the tests. When you turn on a tap to fill a cup you don't think how each drop has travelled halfway round the world to get there. You just want a cup of coffee. Tests always make the same kind of distinction between (a) a requirement of some kind expressed in the language of the domain at the point of testing and (b) the implementation details.
A web test takes the point of view of a web browser. Here, the only commands you're allowed are those which are available in a browser ie clicking links and submitting forms. Don't even *think* about databases at this level. Your site visitors certainly won't. Just describe the behaviour which you expect to observe when you interact with the app via the browser. These are acceptance tests ie top-level UI behaviours which an end-user could write down without any programming knowledge whatsoever.
What would be the requirement expressed in language that an end-user would understand?working on: Aperiplus, Rephactor, Phemto
useful links: xUnit test patterns, martinfowler.com, c2 wiki
-
Sep 2, 2008, 20:42 #7
- Join Date
- Dec 2007
- Posts
- 348
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Well, the requirement would be that on submitting a form to the website to add a new topic to a forum, they are forwarded to a page which shows the new topic on screen, or if the submission was invalid, they'd be forwarded to an error page.
So you're saying I should only do something like:
<?php
$this->post('topic.php', $invalidParams);
$this->assertText('The following errors occurred:'); //part of InvalidSubmissionView
$this->post('topic.php', $validParams);
$this->assertText('Viewing topic :: '.$validParams['title']); //part of ShowTopicView
?>
Is that right?
-
Sep 3, 2008, 06:41 #8
- Join Date
- Sep 2003
- Location
- Glasgow
- Posts
- 1,690
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Yes. Something like:
PHP Code:class WhenPostingForumMessages extends WebTestCase {
function testCanPostAMessage() {
// fetch and assert the "submit post" page
$this->get(...);
$this->assertResponse('200');
$this->assertTitle(...);
$this->assertField(...);
$this->assertField(...);
...
...
// enter data and submit the form
$this->setField(...);
$this->setField(...);
$this->click(...);
// assert the post is added to the forum
$this->assertResponse('200');
$this->assertTitle(...);
$this->assertPattern(...);
...
...
}
}
http://www.lastcraft.com/web_tester_documentation.php
http://www.lastcraft.com/form_testing_documentation.phpworking on: Aperiplus, Rephactor, Phemto
useful links: xUnit test patterns, martinfowler.com, c2 wiki
-
Sep 3, 2008, 06:55 #9
- Join Date
- Sep 2003
- Location
- Glasgow
- Posts
- 1,690
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Excuse me there are actually two tests there:
PHP Code:class WhenPostingForumMessages extends WebTestCase {
function testCanOpenSubmitPostPage() {
$this->get(...);
$this->assertResponse('200');
$this->assertTitle(...);
$this->assertField(...);
$this->assertField(...);
...
...
}
function testCanSubmitPost() {
// enter data and submit the form
$this->get(...);
$this->setField(...);
$this->setField(...);
$this->click(...);
// assert the post is added to the forum
$this->assertResponse('200');
$this->assertTitle(...);
$this->assertPattern(...);
...
...
}
}
working on: Aperiplus, Rephactor, Phemto
useful links: xUnit test patterns, martinfowler.com, c2 wiki
-
Sep 6, 2008, 11:20 #10
- Join Date
- Apr 2003
- Location
- London
- Posts
- 2,423
- Mentioned
- 2 Post(s)
- Tagged
- 0 Thread(s)
Hi...
Individually, with a unit test...
PHP Code:class SignUpControllerTest extends UnitTestCase {
function setUp() {
$this->accounts()->deleteAllUsers();
}
function testSuccessfulSignUpRedirectsToWelcome() {
$continuation = new MockContinuation();
$continuation->expectOnce('redirect', array('welcome.html'));
$request = new Request(array('u' => 'marcus', 'p' => 'secret'));
new SignUp($request, $continuation);
}
function accounts() {
return new AccountsFixture();
}
}
PHP Code:class TestOfSignUp extends WebTestCase {
function setUp() {
$this->accounts()->deleteAllUsers();
}
function testSuccessfulSignUpGoesToWelcomePage() {
$this->get($this->home());
$this->click('sign up');
$this->setField('Username:', 'marcus');
$this->setField('Password:', 'secret');
$this->click('Submit');
$this->assertText('Welcome marcus');
}
function accounts() {
return new AccountsFixture();
}
}
When programming I tend to test all the detail in the unit tests (is this the bit you don't trust?) and just confirm the wiring with the web tests.
Before programming I try to capture the acceptance criteria pretty much as the stakeholders say it. They can then see the test being created in front of them.
I suspect you'll get quite a few different answers for this one. Your testing style will depend on your other development practices.
yours, MarcusMarcus Baker
Testing: SimpleTest, Cgreen, Fakemail
Other: Phemto dependency injector
Books: PHP in Action, 97 things
-
Sep 8, 2008, 03:49 #11
- Join Date
- Jan 2004
- Location
- Oslo, Norway
- Posts
- 894
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Dagfinn Reiersøl
PHP in Action / Blog / Twitter
"Making the impossible possible, the possible easy,
and the easy elegant" -- Moshe Feldenkrais
-
Sep 9, 2008, 11:54 #12
- Join Date
- Apr 2003
- Location
- London
- Posts
- 2,423
- Mentioned
- 2 Post(s)
- Tagged
- 0 Thread(s)
Marcus Baker
Testing: SimpleTest, Cgreen, Fakemail
Other: Phemto dependency injector
Books: PHP in Action, 97 things
-
Sep 15, 2008, 14:40 #13
- Join Date
- Jan 2004
- Location
- Oslo, Norway
- Posts
- 894
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Finally got around to answering this. I don't think I can use any actual examples. Let me just illustrate the principle with an example that may be a something of a caricature.
If performance and speed were not an issue, I might do something like this, keeping each test method short and sweet:
PHP Code:class ArticleListTest extends WebTestCase {
function setUp() {
// Some code to log in and go to the article list page
//....
}
function testHttpStatusOk() {
//...
}
function testHasCorrectTitle() {
//...
}
function testHasNoDebugInfoAccidentallyLeftBehind() {
//...
}
}
PHP Code:class VariousPageTests extends WebTestCase {
function testLoginAndArticleList() {
// Some code to log in
//....
$this->assertStartPage();
// Some code to go to article list page
//....
$this->assertArticleListPage();
}
function assertArticleListPage() {
$this->assertHttpStatusOk();
$this->assertHasCorrectTitle();
$this->assertHasNoDebugInfoAccidentallyLeftBehind();
}
function assertStartPage() {
//
}
}
Dagfinn Reiersøl
PHP in Action / Blog / Twitter
"Making the impossible possible, the possible easy,
and the easy elegant" -- Moshe Feldenkrais
Bookmarks