tailcall icon indicating copy to clipboard operation
tailcall copied to clipboard

Add unit tests for CLI

Open tusharmath opened this issue 1 year ago • 18 comments

CLI piece has no unit tests. We need to re-structure the code to be able to write unit tests in the following manner:

Technical Requirements:

  • Implementation should include sending a CLI Command and asserting what's printed on the Console.
  • Avoid using mocks for testing, depend on pure functions as much as possible.
  • Achieve 100% coverage for the CLI modules.

Proposed Architecture

We will take inspiration from the ELM architecture for writing CLI tests.

The main idea for Elm is

We will port it to Rust in the following way


/// Incoming messages
enum Message {
  ServerStart {file_paths: Vec<String>},
  Init
}

/// Represents side-effects that need to be performed by the program
/// Simple dumb commands that are part of the 
enum Command {
  ReadFile {path: String},
  WriteFile {path: String},
  StartServer {port: Int}
}

/// State of the application
struct State {
  // ... fields relevant to our use case
}


/// Our main application contains two components - update and command
struct App<M, S, C> {
  /// Takes in a message and a state and optionally returns a new state
  pub update: Fn(M, S) -> Option<S>,

  /// Takes in a message and a state and optionally returns a command for the 
  /// driver code to execute
  pub command: Fn(M, S) -> Option<C>
}


/// Effect running code
async fn driver(app: App<Message, Model, Command>, s1: State, m1: Message) -> Result<(), String> {
   let s2 = app.update(m1, s1);
   let cmd = app.command(m1, s1);
   let messages = execute_effects(cmd).await?
   for m in messages {
     driver(app, s2, m).await?;
   }
}

Elm Architecture

The idea of ELM architecture is to write, composable applications that are purely functional and perform no side effects. They are essentially functions that take in a message (known as action) and a state and return another message (known as a command) and the updated state. The application is never async, can not panic, doesn't read a globally mutable value, etc. Given the same input, it returns the same output (referentially transparent). All the side-effects are performed outside the application, using a custom runtime that you have to write.

Action: An input message to the application. Representing typically a user-action. Command: A message produced by the application to do something, without actually doing it. It's interpreted by the external runtime. State: An owned state that allows maintaining contexts between each run of the application. For eg: If we build a counter application, the count would be stored within the state.

Because the application can only be interacted with via messages, the application too becomes stateless and very easy to test. Just send in data, and assert on the returned data. You don't need to mock anything. The runtime is responsible for running the application over and over, each time passing it a new message and the updated state. This process continues unless there is a failure or explicit exit command given by the application.

The runtime connects with the underlying drivers that perform the actual side effects. Drivers are generally simple, for eg: making an http request or writing something to disk, etc. They represent the implementation of the commands.

image

tusharmath avatar Oct 09 '23 12:10 tusharmath

💎 $300 bounty created by tailcallhq 🙋 If you'd like to work on this issue, comment below to get assigned 👉 To claim this bounty, submit a pull request that includes the text /claim #450 somewhere in its body 📝 Before proceeding, please make sure you can receive payouts in your country 💵 Payment arrives in your account 2-5 days after the bounty is rewarded 💯 You keep 100% of the bounty award 🙏 Thank you for contributing to tailcallhq/tailcall! 🙋‍♂️ Join our discord channel if you need help.

algora-pbc[bot] avatar Oct 10 '23 04:10 algora-pbc[bot]

/attempt #450

Options

ayewo avatar Oct 10 '23 05:10 ayewo

Action required: Issue inactive for 30 days. Status update or closure in 7 days.

github-actions[bot] avatar Nov 13 '23 18:11 github-actions[bot]

Issue closed after 7 days of inactivity.

github-actions[bot] avatar Nov 20 '23 18:11 github-actions[bot]

Hi ,I would like to contribute towards this issue, can you please assign me to this , also let me know the existing CLI implementations

Vayras avatar Dec 11 '23 14:12 Vayras

Hey @Vayras, @ayewo will complete this work, but we still have some pendencies from the current test setup. It's recommended to refrain from attempting this, as 1. it needs more clarification/better support, and 2. @ayewo will be the one to implement it.

ologbonowiwi avatar Dec 12 '23 14:12 ologbonowiwi

/bounty 300$

tusharmath avatar Dec 19 '23 07:12 tusharmath

may i work on this?

Ashu999 avatar Dec 19 '23 08:12 Ashu999

/attempt #450 I've discussed this with @ayewo, and I think I'll try this one.

I am unfamiliar with ELM architecture, so I'll likely open draft PR(s) along the way and bring discussions on #contributors.

ologbonowiwi avatar Dec 20 '23 03:12 ologbonowiwi

@ologbonowiwi: The Tailcall Inc. team prefers to assign a single contributor to the issue rather than let anyone attempt it right away. We recommend waiting for a confirmation from a member before getting started.

algora-pbc[bot] avatar Dec 20 '23 03:12 algora-pbc[bot]

Relevant stuff regarding Elm Architecture that can help us to understand more about it:

ologbonowiwi avatar Dec 20 '23 04:12 ologbonowiwi

Hey @tusharmath may i get assigned for this one?

Rutik7066 avatar Dec 23 '23 10:12 Rutik7066

@Ashu999 Why don't you give it a shot. @ologbonowiwi You have quite a lot on your plate :)

tusharmath avatar Dec 27 '23 06:12 tusharmath

@Ashu999 Haven't seen any progress on this. Let me know if you wish for someone else to take it.

tusharmath avatar Dec 29 '23 07:12 tusharmath

@Ashu999 Haven't seen any progress on this. Let me know if you wish for someone else to take it.

yeah you can assign it someone else, I'm mostly looking into @link one right now

Ashu999 avatar Dec 29 '23 07:12 Ashu999

@tusharmath happy to have a look into this :)

SourikAdhikary avatar Dec 29 '23 09:12 SourikAdhikary

@SourikAdhikary Feel free to attempt.

tusharmath avatar Dec 31 '23 13:12 tusharmath

@SourikAdhikary Feel free to attempt.

Will look into this from today.

SourikAdhikary avatar Jan 02 '24 21:01 SourikAdhikary

@tusharmath There is some family emergency at my end. Feel free to assign it to someone else. If no one takes it up I'll have a swing at it next week.

SourikAdhikary avatar Jan 05 '24 01:01 SourikAdhikary

Action required: Issue inactive for 30 days. Status update or closure in 7 days.

github-actions[bot] avatar Feb 04 '24 02:02 github-actions[bot]

Issue closed after 7 days of inactivity.

github-actions[bot] avatar Feb 11 '24 03:02 github-actions[bot]