Unit testing (once again)

Milian Wolff mail at milianw.de
Thu Feb 9 13:39:38 UTC 2012


On Wednesday 08 February 2012 21:22:26 Miha Čančula wrote:
> 2012/2/8 Milian Wolff <mail at milianw.de>
> 
> > Aleix Pol, 08.02.2012:
> > > On Wed, Feb 8, 2012 at 5:23 PM, Miha Čančula <miha at noughmad.eu> wrote:
> > > > 2012/2/8 Aleix Pol <aleixpol at kde.org>
> > 
> > <snip>
> > 
> > > >> To extract the information, the view plugin will load all the plugins
> > > >> that implement the UnitTestProvider interface and ask for the
> > > >> provided
> > > >> information. Here's some rough idea of what I think this interface
> > > >> might have looked like.
> > > >> 
> > > >> class Test {
> > > >> 
> > > >>   QString executable(); //maybe a launcher?
> > > >>   QMap<QString, QStringList> cases(); //test name with the arguments
> > > >> 
> > > >> to pass to the execution
> > > >> };
> > > >> 
> > > >> class IUnitTestProvider {
> > > >> 
> > > >>    virtual QMap<KUrl, Test> retrieveTests() = 0;
> > > >> 
> > > >> };
> > > > 
> > > > This is basically what I had in mind, except for the tree structure
> > 
> > (and
> > 
> > > > asynchronous operation, and checking whether this particular provider
> > 
> > is
> > 
> > > > the right one for a project). My question is where to put the Test
> > > > class. It's possible to avoid it altogether by replacing it with a
> > > > QPair<QString, QStringList> or something even more convoluted, but
> > > > that
> > > > looks ugly. On the other hand, an ugly typedef is still better than a
> > > > whole separate library.
> > > 
> > > It has to be together with the interface, because the interface
> > > depends on it. I think it's fine if it's inside interfaces.
> > 
> > Just make it a pure abstract interface as well.
> > 
> > namespace KDevelop {
> > class ITestSuite
> > {
> > 
> >  ILaunchConfiguration* launcherForAllCases() const  = 0;
> >  ILaunchConfiguration* launcherForCase(const QString& case) const  = 0;
> >  ILaunchConfiguration* launcherForCases(const QStringList& cases) const  =
> > 
> > 0;
> > 
> >  QStringList cases() const = 0;
> >  
> >  KUrl url() const = 0;
> > 
> > };
> > }
> > Q_DECLARE_INTERFACE(KDevelop::ITest)
> 
> This looks clean, but I think at least the data members (list of cases,
> url, name) don't have to be virtual.

but then you need to link to a lib, with the above you don't need that. And 
note that the above leaves it to the implementation on where to get the cases 
from. For example it could be the keys of a hash map. If one would need to 
pass the qstringlist directly to some setter function one would actually waste 
space.

same for the url, maybe you associate it with an indexed topducontext or 
something and return the url from that.

> > And personally, I would rather create a test controller where unit test
> > suites
> > can be added/removed. I.e.:
> > 
> > class ITestController
> > {
> > 
> >  void addTestSuite(ITestSuite* suite);
> >  void removeTestSuite(ITestSuite* suite);
> > 
> > };
> > 
> > This way plugins can easily add test suites by just implementing a
> > ITestSuite
> > class and registering it at the controller.
> 
> So you want global testproviders to be global plugins with no interface
> that float around, look for tests and report them? Sounds simple enough on
> the plugin side, but isn't that a slight waste of resources?

how so? what resources are wasted? note:

- cmake could directly, in the project manager code, report ctests
- all other plugins need some special logic anyways, for php e.g. I'd probably 
put that logic into the php lang support and report testcases whenever I find 
subclasses of PHPUnit_Framework_TestCase

> And the
> controller would have to be globally accessible, in shell perhaps?

yes, but it can just as easily live in a plugin. Query for the plugin that 
offers that interface, and get the plugin's extension for that interface. Just 
like IMakeBuilder is used.

-- 
Milian Wolff
mail at milianw.de
http://milianw.de




More information about the KDevelop-devel mailing list