Well listen, we have two modes of operation. It's either html/js/css in the classic sense, or Go templating with some tailwind and JQuery (or whatever the kids are calling it these days). In the case of react, something totally different. But essentially when you try to go that middle path with something that defines its own syntax, it starts to bleed into everything. It's not self contained. I'd argue maybe tailwind is like that as well, so you want to put it in templates or something. But if your htmx code lives in your actual code the way it does with Go a lot of the times because they promote building these partial functions, it looks horrible, very hard to reason or manage. I'm not talking one or two snippets, I'm talking when you have a full blown web app.
The reality is it's going to suit some people and some languages really well and others not so well. I think I like html/css/js and using AI to generate that. But I also like Go templates and trying to isolate that in a programmatic way. I find htmx in principle, a good idea, but when I actually tried to use it, fundamentally the wrong tool for me.
That's why you need something that lets you componentize your templates. React did this really well with JSX. But classic-style templating languages are not great at this. Django just recently introduced a 'partial templates' feature. I built my own: https://github.com/yawaramin/dream-html/blob/todoapp/app/REA...
> Zig doesn't even pretend to do memory safety - if you don't free something manually it won't get freed
Preventing memory leaks isn't normally what people mean by "memory safety".
As an aside: a common memory management approach used in Zig is to have a dedicated memory pool for an operation and simply free all of the memory after the operation is over instead of freeing individual allocations.
> Preventing memory leaks isn't normally what people mean by "memory safety".
People do sometimes expect it to be encompassed by memory safety, even though the Rust documentation clearly states that it does not prevent memory leaks in safe code and offers several obvious ways to deliberately leak memory.
I don't think the character is that uncommon in the output of slightly-sophisticated writers and is not hard to generate (e.g., on macOS pressing option-shift-minus generates an em-dash).
In fact, on macOS and iOS simply typing two dashes (--) gets autocorrected to an em dash. I used it heavily, which was a bit sloppy since it doesn't also insert the customary hair spaces around the em dash.
Incidentally, I turned this autocorrection off when people started associating em dashes with AI writing. I now leave them manual double dashes--even less correct than before, but at least people are more likely to read my writing.
Thanks for the support! It means a lot, especially from someone who shares the pytest frustration.
About bare `assert`s. Vedro is actually flexible enough to use any matchers you prefer, but let me share why I stick with plain asserts:
1. In most editor themes, `assert` jumps out with distinct syntax highlighting. When scanning tests, I can quickly spot the assertions and understand what's being tested.
2. The expressions feel cleaner to me:
assert error_code not in [400, 500]
# vs
assert_that(error_code, is_not(any_of(400, 500))) # hamcrest
3. I like that there's nothing new to learn, the expressions work exactly like they do in any Python code, with no special test behavior or surprises.
Would love to hear what specifically bothers you about bare asserts, always looking to understand different perspectives on testing ergonomics!
Your first and second points makes sense. They don't matter much to me, but I see how others could value those things.
Aside: I also don't like the hamcrest syntax. I also don't love unittest's syntax but it's OK and it's pervasive (i.e., available in the stdlib).
The third point is where I start to disagree more strongly.
> I like that there's nothing new to learn, the expressions work exactly like they do in any Python code, with no special test behavior or surprises.
This doesn't seem true to me.
> the expressions work exactly like they do in any Python code
Not to my mind. In normal Python, an assertion communicates something that is unequivocally believed to be true, not something that may or may not be true (a test). Let me see if I can explain it this way, I often use asserts in tests to show (and enforce) something that I believe to be true and must be true, before the test can have any meaning. E.g.,
The "assert" communicates that this is a precondition, the "self.AssertTrue" communicates that this is a test.
I can 100% see that others might not see/care about the distinction, but I think it is important.
> no special test behavior
Well, that's not quite true. You have to handle the AssertionError specially and do some fairly magical work to figure out the details of the expression that failed. The unittest-style assertions just report the values passed into them.
I don't really like that magic, both from an aesthetic standpoint and from a least-complexity-in-my-tooling standpoint. Again, I can understand others making different tradeoffs.
Thank you for taking the time to explain your perspective, this is exactly the kind of thoughtful feedback that helps me understand different testing philosophies.
Your distinction between assertions (preconditions/invariants) vs tests (things being verified) is really interesting. I can absolutely see how using different syntax helps communicate intent: "this MUST be true for the test to even make sense" vs "this is what we're actually testing". That semantic clarity is valuable, it reminds me of contract programming in languages like D where preconditions and postconditions have distinct roles.
You're absolutely right about the special assertion handling, that's definitely special behavior and I should have been clearer. What I meant was that the expressions themselves evaluate using Python's normal rules without hidden transformations. For example, Playwright's `expect(loc).to_have_text("text")` silently normalizes whitespace, so "hello world" might match "hello world". With plain asserts, `assert element.text == "hello world"` means exactly that: no normalization, no special matching rules. The expression evaluates the same way it would in a REPL.
But yes, extracting the failure details does require machinery that I'm not thrilled about either. It's the one compromise I made to support the plain assert syntax that many Python developers expect. But actually, you can use the `asserts` helper which does exactly what you described without any special handling:
from vedro import scenario, asserts as _
@scenario
def calculate_discount():
product = ...
discounted = apply_discount(product, 0.2)
_.assert_equal(discounted.price, 80.0)
I appreciate the consideration. I'll be watching Vedro with interest.
I do like the nicer vedro.asserts mechanism. If that works with unittest and pytest it would be really nice. You might get a few converts that way, too.
I think the ambition is much larger than what could be accomplished by part-time volunteer work. It was either this or somehow get a bigcorp to dedicate 2, 5, 10 full time salaries to it.
Honestly it's not clear to me that the money they have in income now is enough to accomplish the ambition, but I guess that's why it is a fundraiser in addition to a financial report.
I'd love to hear more about that.