Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TDD Design question

9 views
Skip to first unread message

Sean DeNigris

unread,
Apr 25, 2009, 7:52:14 PM4/25/09
to
Hi group,

I'm writing a C++ web app test-first using the wt web toolkit (like a
UI framework).

While driving the design of my UI interface, I ended up wanting:

// Interface of UI discovered via mocking
class UI {
public:
...
virtual void addMenu(const std::vector<std::string>& choices) = 0;
};

However, the toolkit creates menus like this:
Wt::WComboBox *combo = new Wt::WComboBox(this);
combo->addItem("Clint Eastwood");
combo->addItem("Mick Jagger");

I don't want the library implementation to bleed into my design i.e.

//I want to write
addMenu(...);

//not
addMenu(...);
for ...
{
addChoice(...);
}

I was thinking of adding a new layer that translates my interface to
the library implementation.

What do you think?

Sean DeNigris

Phlip

unread,
Apr 25, 2009, 10:28:54 PM4/25/09
to
Sean DeNigris wrote:

> I'm writing a C++ web app test-first using the wt web toolkit (like a
> UI framework).

Pretend I'm your boss, peering over your shoulder.

Why not Ruby on Rails? Be prepared to defend this decision. (Yes, even if a boss
told you to do it.)

> While driving the design of my UI interface, I ended up wanting:
>
> // Interface of UI discovered via mocking
> class UI {
> public:
> ...
> virtual void addMenu(const std::vector<std::string>& choices) = 0;
> };
>
> However, the toolkit creates menus like this:
> Wt::WComboBox *combo = new Wt::WComboBox(this);
> combo->addItem("Clint Eastwood");
> combo->addItem("Mick Jagger");
>
> I don't want the library implementation to bleed into my design i.e.
>
> //I want to write
> addMenu(...);
>
> //not
> addMenu(...);
> for ...
> {
> addChoice(...);
> }
>
> I was thinking of adding a new layer that translates my interface to
> the library implementation.
>
> What do you think?

What do this WT's unit tests look like?

If it has none, you have _another_ strike against it. Do not dabble in any
library that does not make unit testing easy.

Finally, if you add this layer (or if you finish the feature first and then
refactor the layer into existence), you must now test and support the layer. Is
that enough trouble for one stoopid menu?

--
Phlip

Phlip

unread,
Apr 25, 2009, 10:33:09 PM4/25/09
to
Sean DeNigris wrote:

> I'm writing a C++ web app test-first using the wt web toolkit (like a
> UI framework).

> What do you think?

El Goog says wt does not say "assert" on its website (site:webtoolkit.eu), and
only says "test" once.

I would reject this library, and inform its user community why I am rejecting
it. The main problem here is, unlike a dumb API like a database, UIs are
extremely tricky beasts, and very hard to unit test. Leaving out the tests does
not just reflect poorly on the quality of this library, and its design process,
it exposes you to slow development as you reinvent the unit test process, AND it
exposes you to risk as this library matures and grows features over time.

--
Phlip

Sean DeNigris

unread,
Apr 25, 2009, 11:08:47 PM4/25/09
to
> Pretend I'm your boss, peering over your shoulder.
>
> Why not Ruby on Rails? Be prepared to defend this decision. (Yes, even if a boss
> told you to do it.)
Ha ha, I was afraid I might get that instead of an answer to the
question :)
I do have my reasons, and I may lay them out, but they are irrelevant
to this discussion.

> What do this WT's unit tests look like?

Same as above. I know what I want works, and I'm working on a small
internal project.

> Finally, if you add this layer (or if you finish the feature first and then
> refactor the layer into existence), you must now test and support the layer. Is
> that enough trouble for one stoopid menu?

I guess what I'm really asking is about the pattern, not the over-
simplified example i.e. assuming that I'm using many API functions
from the library, is another layer a good way to smooth out
differences between my "writing the code I wish I had" (Dave Astels)
and the actual implementation of the library?

Sean

Phlip

unread,
Apr 25, 2009, 11:40:07 PM4/25/09
to
Sean DeNigris wrote:

>> Finally, if you add this layer (or if you finish the feature first and then
>> refactor the layer into existence), you must now test and support the layer. Is
>> that enough trouble for one stoopid menu?

> I guess what I'm really asking is about the pattern, not the over-
> simplified example i.e. assuming that I'm using many API functions
> from the library, is another layer a good way to smooth out
> differences between my "writing the code I wish I had" (Dave Astels)
> and the actual implementation of the library?

Yes - you did get the answer. You must produce this layer by refactoring, you
need unit tests both above and below the layer, and other than that writing a
facade is a best practice here.

May I ask if WT at _least_ lets you test without sending pages through a web server?

Sean DeNigris

unread,
Apr 26, 2009, 10:20:18 AM4/26/09
to
> Yes - you did get the answer. You must produce this layer by refactoring, you
> need unit tests both above and below the layer, and other than that writing a
> facade is a best practice here.
I didn't say you didn't answer, I said I was afraid, lol

> May I ask if WT at _least_ lets you test without sending pages through a web server?

Well, as far as the UI widgets, there are ways to search the widget
tree, so you could do something like:

//Pseudo code
TestAddMenu
{
...
wt_view.addMenu(...)

CHECK(contains_widget(wt_view.count() == 1);
...
}

For the interactivity, I don't know, but it uses Boost Asio sockets.

Is that what you meant?

Phlip

unread,
Apr 26, 2009, 10:33:16 AM4/26/09
to
Sean DeNigris wrote:

>> May I ask if WT at _least_ lets you test without sending pages through a web server?
>
> Well, as far as the UI widgets, there are ways to search the widget
> tree, so you could do something like:
>
> //Pseudo code
> TestAddMenu
> {
> ...
> wt_view.addMenu(...)
>
> CHECK(contains_widget(wt_view.count() == 1);
> ...
> }

(Is that UnitTest++?)

I think that wt_view is an object model, and I think you are querying it back
before you render it into raw HTML.

(I also suspect wt_view is a deep model that tends to hide the raw HTML.)

The majority of HTML testing I have learned uses this system:

- call production code to build a view
- render the View into HTML
- don't send the HTML to a server or browser ("Mock the Web Server")
- parse the HTML as an XML model
- query that the raw HTML you want appears.

Your wt_view might insulate you from lots of HTML, but it's always nice to check it.

And, no, I don't mean Boost::asio. When you mock the web server, you mock a post
by constructing the raw HTTP POST command that a browser would have constructed,
then send it directly into your server Action that would have process it.

Look up how Ruby on Rails does all this - for a raw HTML system, it is exemplary.

Sean DeNigris

unread,
Apr 26, 2009, 11:40:14 AM4/26/09
to
> (Is that UnitTest++?)
I actually use Boost Test, but simplified the example

> I think that wt_view is an object model, and I think you are querying it back
> before you render it into raw HTML.

Yes, should've explained more. wt_view would be a "thin GUI" model
class which implements its functionality via the wt library

> (I also suspect wt_view is a deep model that tends to hide the raw HTML.)

> Your wt_view might insulate you from lots of HTML, but it's always nice to check it.

The wt library figures out the best way to create the web ui. It may
use raw HTML, AJAX & DHTML, or whatever, depending on the client
browser's capabilities. I never have to get involved in anything web-
related

> And, no, I don't mean Boost::asio. When you mock the web server, you mock a post
> by constructing the raw HTTP POST command that a browser would have constructed,
> then send it directly into your server Action that would have process it.

Well, one way wt can be run is as a standalone web server (which is
usually run behind a reverse-proxy). This simplifies testing because
you can have it listen to a local IP and send HTTP directly to it

> Look up how Ruby on Rails does all this - for a raw HTML system, it is exemplary.

I've heard a lot about it. I will probably investigate it at some
point.

Sean

Phlip

unread,
Apr 26, 2009, 12:09:48 PM4/26/09
to
Sean DeNigris wrote:

>> And, no, I don't mean Boost::asio. When you mock the web server, you mock a post
>> by constructing the raw HTTP POST command that a browser would have constructed,
>> then send it directly into your server Action that would have process it.

> Well, one way wt can be run is as a standalone web server (which is
> usually run behind a reverse-proxy). This simplifies testing because
> you can have it listen to a local IP and send HTTP directly to it

That's not "unit" testing. The wire will add noise to the tests' signal.

Can you just call the same method as the CGI (or Servlets) layer will call?

And how about you ask these questions on the wt support forum?

James Peckham

unread,
May 25, 2009, 1:23:57 PM5/25/09
to
>    Phlip- Hide quoted text -
>
> - Show quoted text -

Oh in come the 'boss' argument. That's like going to the mechanic and
telling the mechanic how to do his job. You're the mechanic. Do what's
best for the car. Bosses sign the checks so make sure to treat them
with respect but inform them why you do what you're doing. If in the
end they don't agree, then get their sign off on it and cover your
ass. You should be doing what's right for the code, that's your job.
Sorry for the rant, I'm just tired of the 'ticking timebomb' scenario.
We should always be doing the right thing for the code because someone
besides us will have to maintain this code and support it.

0 new messages