pgtap icon indicating copy to clipboard operation
pgtap copied to clipboard

Created faking and mocking functions

Open v-maliutin opened this issue 10 months ago • 17 comments

I developed some functions to make writing tests easier. There are examples in the source code. Also, I wrote an article on habr. Here it is https://habr.com/ru/companies/gnivc/articles/877314/. I know it is in Russian, but hope modern translation will help. Anyway such functionality is in any modern language and wide known. I just bringing it in PG world. One more thing. I am going to introduce my work and pgTap at pgConf in Moscow on March 31 2025.

v-maliutin avatar Mar 13 '25 17:03 v-maliutin

@theory Hi! Could you please let me know what you think about my PR. I'd appreciate it.

v-maliutin avatar May 13 '25 10:05 v-maliutin

Sorry, @v-maliutin, hyper busy rn, but will get to it.

theory avatar May 22 '25 20:05 theory

Not a full review, but a couple comments:

AFAIK, there's no reason to modify the unpackaged script.

Instead of building a function body via ||, I think it would be a lot clearer to use format().

jnasbyupgrade avatar Jun 02 '25 23:06 jnasbyupgrade

Not a full review, but a couple comments:

AFAIK, there's no reason to modify the unpackaged script.

Instead of building a function body via ||, I think it would be a lot clearer to use format().

@jnasbyupgrade thank you for your review. Rolled back changes in Unpackaged Regarding format vs ||. May I stay as is? Just I always lost in '%1L, %2I, %3s'. Especially when there are a lot of %. Anyway I can fix it if you insist. This is not a big problem for me.

v-maliutin avatar Aug 24 '25 15:08 v-maliutin

@theory

Hi, I am going to implement the following features. Please let me know if you think they are a good idea too.

  1. Spy on a routine. This feature would log parameter values.
  2. Spy on a table. A trigger logging inserted/updated/deleted values. Something like a profiler.
  3. Make the output of runtests a standard dataset. It would help to write a tool running tests. Let's say a plugin to DBeaver.
  4. Mocking of procedures.
  5. Special mock to arrange a profiler feature

v-maliutin avatar Nov 01 '25 03:11 v-maliutin

@theory

Hi, I am going to implement the following features. Please let me know if you think they are a good idea too.

Seems like it, yes, but again I think this is full-featured enough that it might be better developed and distributed as its own extension.

theory avatar Nov 01 '25 16:11 theory

Honestly this is a huge feature that I think should probably be its own extension, either distributed separately and depending on pgtap (perhaps a release that includes changes to tap_funky that it requires) or else a separate extension as part of the pgTAP distribution. I'm leaning toward the former, at least as you work through the process, because I'm not sure I have the capacity to take on maintaining such a huge feature I don't use. I'm happy to review code and make recommendations if you decide to distribute it as its own extension.

I am pleasantly surprised to read this. Okay, no problem, I can go with my own extension depending on pgTap. Could you please explain. When you talk about a separate extension as part of the pgTap what do you mean exactly?

v-maliutin avatar Nov 02 '25 11:11 v-maliutin

A project can have more than one extension. This one has three (pgtap, pgtap-core, and pgtap-schema. Each just needs its own control file, SQL files, and entry in META.json. But I think it'd be adding a lot of maintenance overhead to the maintenance of pgTAP to add another here, TBH.

theory avatar Nov 02 '25 13:11 theory

So, what is the best solution?

v-maliutin avatar Nov 02 '25 13:11 v-maliutin

So, what is the best solution?

I suggest you continue developing in your own project, a separate repo. I'd be happy to review stuff there if yo find it helpful (and I'll make a whole lot fewer style comments :-)). Make a new PR for revisions to tap_funky if you need them.

Overall this will give you a lot more freedom and control over the extension and how it works.

theory avatar Nov 02 '25 15:11 theory

So, what is the best solution?

I suggest you continue developing in your own project, a separate repo. I'd be happy to review stuff there if yo find it helpful (and I'll make a whole lot fewer style comments :-)). Make a new PR for revisions to tap_funky if you need them.

Overall this will give you a lot more freedom and control over the extension and how it works.

Hello @theory Okay, will go with your suggestion. I'll close this PR and create a new one to fix tap_funky. I've got a couple of questions could you please explain them. What are those extensions for? I mean pgtap-core and pgtap-schema. Should I care of them in some way? And another one question. Please let me know how do you create html from pgtap.mmd. Is there a standard tool?

v-maliutin avatar Nov 06 '25 03:11 v-maliutin

What are those extensions for? I mean pgtap-core and pgtap-schema.

They're for embedding in other extension packages. For example, semver includes pgtap-core.sql so it can use core pgTAP features without a full extension installation process.

Should I care of them in some way?

No, they were just examples, and not great ones, TBH, since they have no control files.

And another one question. Please let me know how do you create html from pgtap.mmd. Is there a standard tool?

PGXN uses Text::Markup to render documentation as HTML; for .mmd files it uses Text::MultiMarkdown. I don't recommend it anymore, though, unless you really need definition lists; instead use .md files, which PGXN converts to HTML using cmark.

HTH!

theory avatar Nov 09 '25 20:11 theory

@theory I moved all my code to my own repo.

So it replaces the function in the same schema? I presume you're depending on a transaction ROLLBACK to rollback the mock function, yes?

Yes, that's how it works. Do you see any problems with that?

Seems like there are some conditions that are ignored here, yes? Should it raise an error for unsupported conditions, e.g., a set-returning C function.

Did not think about C functions, but it seems I have to. Anyway, I have to handle a case when user did not provide schema.

I love your suggestion to review my code. Will ask you.

I have fixed most issues you shown in my repo.

v-maliutin avatar Nov 15 '25 12:11 v-maliutin

Reviewing the changes to tap_funky, I'm starting to wonder whether they're needed in pgTAP, or if you'd be able to use a function or view in your mock extension to get all the info you need for mocking. What do you think?

theory avatar Nov 16 '25 22:11 theory

Reviewing the changes to tap_funky, I'm starting to wonder whether they're needed in pgTAP, or if you'd be able to use a function or view in your mock extension to get all the info you need for mocking. What do you think?

You wrote early.

I think should probably be its own extension, either distributed separately and depending on pgtap (perhaps a release that includes changes to tap_funky that it requires) or else a separate extension as part of the pgTAP distribution.

That's why I created my own extension and made this change to tap_funky.

Just after creating a new extension, I realized that my code depends on your cool feature which rolls back any changes made during tests immediately after they finish.

Therefore, my code doesn't make sense without pgTap. In other words, my features are being developed specifically for a unit testing framework.

I can keep my code in my fork. However, could you clarify what you meant by

else a separate extension as part of the pgTAP distribution

v-maliutin avatar Nov 22 '25 15:11 v-maliutin

Just after creating a new extension, I realized that my code depends on your cool feature which rolls back any changes made during tests immediately after they finish.

That's just transaction rollback, it's not controlled by pgTAP but by the tests themselves.

I can keep my code in my fork. However, could you clarify what you meant by

else a separate extension as part of the pgTAP distribution

I tried to get at that in this reply.

theory avatar Nov 24 '25 16:11 theory