Skip to content

An idea for tests #174

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
johnlepikhin opened this issue Apr 18, 2025 · 1 comment
Closed

An idea for tests #174

johnlepikhin opened this issue Apr 18, 2025 · 1 comment

Comments

@johnlepikhin
Copy link

As a consequence of issue #169, I just wanted to suggest a technique of testing parsers and printers. Parsing and printing (serializers and deserializers) are mutually inverse functions: the result of print(parse(some_text)) should be some_text itself – in case if some_text is well-formatted. Thus, it is really easy to write parser+printer tests literally in declarative style:

let cases = [
  ("**some bold text**", "should support bold text"),
  "plain text\n\nwith newlines", "should support text with newlines"),
  ...
  ...
];

#[test]
fn roundtrip() {
  for (orig_md_text, error_message) in cases {
    let ast = markdown::to_mdast(&orig_md_text, &markdown::ParseOptions::default()).unwrap();
    let formatted_md_text = to(&ast).unwrap();
    assert_eq!(formatted_md_text, orig_md_text, error_message)
  }
}
@ChristianMurphy
Copy link
Collaborator

ChristianMurphy commented Apr 18, 2025

Heya @johnlepikhin 👋
Property tests are something this project is open to!
There are already some which are checked, like the parser should not panic:

#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: &[u8]| {
if let Ok(s) = std::str::from_utf8(data) {
let _ = markdown::to_html(s);
let _ = markdown::to_html_with_options(s, &markdown::Options::gfm());
let _ = markdown::to_mdast(s, &markdown::ParseOptions::default());
let _ = markdown::to_mdast(s, &markdown::ParseOptions::gfm());
let _ = markdown::to_mdast(s, &markdown::ParseOptions::mdx());
}
});

Parsing and printing (serializers and deserializers) are mutually inverse functions

This is not true.
markdown-rs is an abstract syntax tree library, the abstract part is important here, it means structure will be preserved, but the individual characters used for formatting may not.

As an example, these are both strong text

**Bold**
__Bold__

when run through markdown-rs you will get strong text back on the other side, but you are not guaranteed to get the same marker characters that were originally used, those were abstracted.

fn roundtrip() {

round trip testing is another useful approach, this is already done on the JavaScript implementation, remark, but not yet in markdown-rs.
The property to test is that if you serialize an mdast AST to to markdown text, then parse than markdown text into an mdast AST again, the trees should have the same structure (same node types).
This testing approach could also be applied here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants