Repository: qBraid/pyqasm

Issue:
[FEATURE] Migrate `format_qasm` from qBraid SDK
### Feature Description

Migrate the `qbraid.passes.qasm.format::format_qasm` and helper methods to the `QasmModule.format_qasm()` method. 

### Implementation (Optional)

_No response_

Hints from issue comments:

Solution patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 20ed382..cf7823e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,12 +15,15 @@ Types of changes:
 ## Unreleased
 
 ### Added
+- Added a `dumps` and `formatted_qasm` method to the `QasmModule` class to allow for the conversion of a `QasmModule` object to a string representation of the QASM code ([#71](https://github.com/qBraid/pyqasm/pull/71))
 
 ### Improved / Modified
+- Changed the `__init__` method for the `QasmModule` class to only accept an `openqasm3.ast.Program` object as input ([#71](https://github.com/qBraid/pyqasm/pull/71))
 
 ### Deprecated
 
 ### Removed
+- Removed the `from_program` method from the `QasmModule` class ([#71](https://github.com/qBraid/pyqasm/pull/71))
 
 ### Fixed
 
diff --git a/docs/index.rst b/docs/index.rst
index 4d1ce7f..6613874 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -121,7 +121,7 @@ Example
    module = pyqasm.load(qasm)
    module.unroll()
 
-   unrolled_qasm = module.unrolled_qasm
+   unrolled_qasm = module.dumps()
 
    print(unrolled_qasm)
 
diff --git a/examples/README.md b/examples/README.md
index cbc9dd9..11d1d27 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -32,7 +32,7 @@ result = measure q;
 
 qasm_module = pyqasm.load(program)
 qasm_module.unroll()
-print(qasm_module.unrolled_qasm)
+print(qasm_module.dumps())
 ```
 
 ```text
diff --git a/examples/unroll_example.py b/examples/unroll_example.py
index 044879e..8b0b303 100755
--- a/examples/unroll_example.py
+++ b/examples/unroll_example.py
@@ -73,4 +73,4 @@ def deutsch_jozsa(qubit[N] q_func, qubit[1] ancilla_q) {
 qasm_module = pyqasm.load(qasm_program)
 qasm_module.unroll()
 
-print(qasm_module.unrolled_qasm)
+print(qasm_module.dumps())
diff --git a/pyqasm/entrypoint.py b/pyqasm/entrypoint.py
index 2fae470..6986c85 100644
--- a/pyqasm/entrypoint.py
+++ b/pyqasm/entrypoint.py
@@ -54,6 +54,6 @@ def load(program: openqasm3.ast.Program | str) -> QasmModule:
     program.version = str(float(program.version))
 
     qasm_module = Qasm3Module if program.version.startswith("3") else Qasm2Module
-    module = qasm_module.from_program(program)
+    module = qasm_module("main", program)
 
     return module
diff --git a/pyqasm/modules/base.py b/pyqasm/modules/base.py
index e56228e..b7a33aa 100644
--- a/pyqasm/modules/base.py
+++ b/pyqasm/modules/base.py
@@ -17,7 +17,7 @@
 from typing import Optional
 
 import openqasm3.ast as qasm3_ast
-from openqasm3.ast import Include, Program, Statement
+from openqasm3.ast import Include, Program
 
 from pyqasm.analyzer import Qasm3Analyzer
 from pyqasm.elements import ClbitDepthNode, QubitDepthNode
@@ -35,10 +35,10 @@ class QasmModule(ABC):  # pylint: disable=too-many-instance-attributes
         statements (list[Statement]): list of openqasm3 Statements.
     """
 
-    def __init__(self, name: str, program: Program, statements: list):
+    def __init__(self, name: str, program: Program):
         self._name = name
         self._original_program = program
-        self._statements = statements
+        self._statements = program.statements
         self._qubit_registers: dict[str, int] = {}
         self._num_qubits = -1
         self._qubit_depths: dict[tuple[str, int], QubitDepthNode] = {}
@@ -47,7 +47,6 @@ def __init__(self, name: str, program: Program, statements: list):
         self._clbit_depths: dict[tuple[str, int], ClbitDepthNode] = {}
         self._has_measurements: Optional[bool] = None
         self._validated_program = False
-        self._unrolled_qasm = ""
         self._unrolled_ast = Program(statements=[Include("stdgates.inc")])
 
     @property
@@ -120,32 +119,6 @@ def unrolled_ast(self, value: Program):
         """Setter for the unrolled AST"""
         self._unrolled_ast = value
 
-    @property
-    def unrolled_qasm(self) -> str:
-        """Returns the unrolled qasm for the given module"""
-        return self._qasm_ast_to_str(self._unrolled_ast)
-
-    @unrolled_qasm.setter
-    def unrolled_qasm(self, value: str):
-        """Setter for the unrolled qasm"""
-        self._unrolled_qasm = value
-
-    @classmethod
-    def from_program(cls, program: Program):
-        """
-        Construct a Qasm3Module from a given openqasm3.ast.Program object
-        """
-        statements: list[Statement] = []
-
-        for statement in program.statements:
-            statements.append(statement)
-
-        return cls(
-            name="main",
-            program=program,
-            statements=statements,
-        )
-
     def has_measurements(self):
         """Check if the module has any measurement operations."""
         if self._has_measurements is None:
@@ -195,7 +168,6 @@ def remove_measurements(self, in_place: bool = True):
         curr_module._has_measurements = False
         curr_module._statements = stmts_without_meas
         curr_module._unrolled_ast.statements = stmts_without_meas
-        curr_module._unrolled_qasm = self._qasm_ast_to_str(curr_module._unrolled_ast)
 
         return curr_module
 
@@ -225,7 +197,6 @@ def remove_barriers(self, in_place: bool = True):
 
         curr_module._statements = stmts_without_barriers
         curr_module._unrolled_ast.statements = stmts_without_barriers
-        curr_module._unrolled_qasm = self._qasm_ast_to_str(curr_module._unrolled_ast)
 
         return curr_module
 
@@ -438,12 +409,31 @@ def unroll(self, **kwargs):
         except (ValidationError, UnrollError) as err:
             # reset the unrolled ast and qasm
             self.num_qubits, self.num_clbits = -1, -1
-            self._unrolled_qasm = ""
             self._unrolled_ast = Program(
                 statements=[Include("stdgates.inc")], version=self.original_program.version
             )
             raise err
 
+    def dumps(self) -> str:
+        """Return the string representation of the QASM program
+
+        Returns:
+            str: The string representation of the module
+        """
+
+        if len(self.unrolled_ast.statements) > 1:
+            return self._qasm_ast_to_str(self.unrolled_ast)
+        return self._qasm_ast_to_str(self.original_program)
+
+    def formatted_qasm(self) -> str:
+        """Return the formatted QASM program
+           Removes empty lines and comments from the QASM program
+
+        Returns:
+            str: The formatted QASM program
+        """
+        return self.dumps()
+
     def copy(self):
         """Return a deep copy of the module"""
         return deepcopy(self)
diff --git a/pyqasm/modules/qasm2.py b/pyqasm/modules/qasm2.py
index ee66485..b8644f2 100644
--- a/pyqasm/modules/qasm2.py
+++ b/pyqasm/modules/qasm2.py
@@ -35,13 +35,8 @@ class Qasm2Module(QasmModule):
         statements (list[Statement]): list of openqasm2 Statements.
     """
 
-    def __init__(
-        self,
-        name: str,
-        program: Program,
-        statements: list,
-    ):
-        super().__init__(name, program, statements)
+    def __init__(self, name: str, program: Program):
+        super().__init__(name, program)
         self._unrolled_ast = Program(statements=[Include("qelib1.inc")], version="2.0")
         self._whitelist_statements = {
             qasm3_ast.BranchingStatement,
@@ -97,7 +92,7 @@ def to_qasm3(self, as_str: bool = False) -> Union[str, Qasm3Module]:
                 stmt.filename = "stdgates.inc"
                 break
         qasm_program.version = "3.0"
-        return dumps(qasm_program) if as_str else Qasm3Module.from_program(qasm_program)
+        return dumps(qasm_program) if as_str else Qasm3Module(self._name, qasm_program)
 
     def accept(self, visitor):
         """Accept a visitor for the module
diff --git a/pyqasm/modules/qasm3.py b/pyqasm/modules/qasm3.py
index 6f0197a..a19182c 100644
--- a/pyqasm/modules/qasm3.py
+++ b/pyqasm/modules/qasm3.py
@@ -28,13 +28,8 @@ class Qasm3Module(QasmModule):
         statements (list[Statement]): list of openqasm3 Statements.
     """
 
-    def __init__(
-        self,
-        name: str,
-        program: Program,
-        statements: list,
-    ):
-        super().__init__(name, program, statements)
+    def __init__(self, name: str, program: Program):
+        super().__init__(name, program)
         self._unrolled_ast = Program(statements=[Include("stdgates.inc")], version="3.0")
 
     def _qasm_ast_to_str(self, qasm_ast):


Test patch:
diff --git a/tests/qasm2/test_declarations.py b/tests/qasm2/test_declarations.py
index dacf14b..7be615e 100644
--- a/tests/qasm2/test_declarations.py
+++ b/tests/qasm2/test_declarations.py
@@ -13,7 +13,10 @@
 declarations.
 
 """
+import pytest
+
 from pyqasm.entrypoint import load
+from pyqasm.exceptions import ValidationError
 from tests.utils import check_unrolled_qasm
 
 
@@ -35,7 +38,7 @@ def test_qubit_declarations():
 
     result = load(qasm2_string)
     result.unroll()
-    unrolled_qasm = result.unrolled_qasm
+    unrolled_qasm = result.dumps()
 
     check_unrolled_qasm(unrolled_qasm, expected_qasm)
 
@@ -59,7 +62,7 @@ def test_clbit_declarations():
 
     result = load(qasm2_string)
     result.unroll()
-    unrolled_qasm = result.unrolled_qasm
+    unrolled_qasm = result.dumps()
 
     check_unrolled_qasm(unrolled_qasm, expected_qasm)
 
@@ -90,6 +93,20 @@ def test_qubit_clbit_declarations():
 
     result = load(qasm2_string)
     result.unroll()
-    unrolled_qasm = result.unrolled_qasm
+    unrolled_qasm = result.dumps()
 
     check_unrolled_qasm(unrolled_qasm, expected_qasm)
+
+
+@pytest.mark.skip(reason="Not implemented yet")
+def test_invalid_qasm2_declarations():
+    """Test that invalid qasm2 raises error"""
+    invalid_qasm2 = """
+    OPENQASM 2.0;
+    include "qelib1.inc";
+    qubit[2] q;
+    qubit[4] q2;
+    qubit q3;
+    """
+    with pytest.raises(ValidationError):
+        load(invalid_qasm2).validate()
diff --git a/tests/qasm2/test_format.py b/tests/qasm2/test_format.py
new file mode 100644
index 0000000..0a15ebd
--- /dev/null
+++ b/tests/qasm2/test_format.py
@@ -0,0 +1,68 @@
+# Copyright (C) 2024 qBraid
+#
+# This file is part of pyqasm
+#
+# Pyqasm is free software released under the GNU General Public License v3
+# or later. You can redistribute and/or modify it under the terms of the GPL v3.
+# See the LICENSE file in the project root or <https://www.gnu.org/licenses/gpl-3.0.html>.
+#
+# THERE IS NO WARRANTY for pyqasm, as per Section 15 of the GPL v3.
+
+"""
+Module containing unit tests for program formatting
+
+"""
+
+from pyqasm.entrypoint import load
+from tests.utils import check_unrolled_qasm
+
+
+def test_comments_removed_from_qasm():
+    qasm2_string = """
+    OPENQASM 2.0;
+    include "qelib1.inc";
+    // This is a comment
+    qreg q[1];
+    // This is another comment
+    h q[0];
+    """
+    expected_qasm2_string = """
+    OPENQASM 2.0;
+    include "qelib1.inc";
+    qreg q[1];
+    h q[0];
+    """
+
+    result = load(qasm2_string)
+    actual_qasm2_string = result.formatted_qasm()
+
+    check_unrolled_qasm(actual_qasm2_string, expected_qasm2_string)
+
+
+def test_empty_lines_removed_from_qasm():
+    qasm2_string = """
+    OPENQASM 2.0;
+
+
+    include "qelib1.inc";
+
+
+
+    qreg q[1];
+    h q[0];
+
+
+
+    
+    """
+    expected_qasm2_string = """
+    OPENQASM 2.0;
+    include "qelib1.inc";
+    qreg q[1];
+    h q[0];
+    """
+
+    result = load(qasm2_string)
+    actual_qasm2_string = result.formatted_qasm()
+
+    check_unrolled_qasm(actual_qasm2_string, expected_qasm2_string)
diff --git a/tests/qasm2/test_operations.py b/tests/qasm2/test_operations.py
index 6098972..0194f3b 100644
--- a/tests/qasm2/test_operations.py
+++ b/tests/qasm2/test_operations.py
@@ -60,7 +60,7 @@ def test_whitelisted_ops():
 
     result = load(qasm2_string)
     result.unroll()
-    check_unrolled_qasm(result.unrolled_qasm, expected_qasm)
+    check_unrolled_qasm(result.dumps(), expected_qasm)
 
 
 def test_subroutine_blacklist():
diff --git a/tests/qasm2/test_rotation_gates.py b/tests/qasm2/test_rotation_gates.py
index e02a9c9..e71aa19 100644
--- a/tests/qasm2/test_rotation_gates.py
+++ b/tests/qasm2/test_rotation_gates.py
@@ -41,7 +41,7 @@ def test_convert_qasm_one_param():
 """
     result = load(qasm_in)
     result.unroll()
-    unrolled_qasm = result.unrolled_qasm
+    unrolled_qasm = result.dumps()
     check_unrolled_qasm(unrolled_qasm, expected_out)
 
 
@@ -64,7 +64,7 @@ def test_convert_qasm_two_param():
 """
     result = load(qasm_in)
     result.unroll()
-    unrolled_qasm = result.unrolled_qasm
+    unrolled_qasm = result.dumps()
     check_unrolled_qasm(unrolled_qasm, expected_out)
 
 
@@ -92,7 +92,7 @@ def test_convert_qasm_three_qubit_gate():
 """
     result = load(qasm_in)
     result.unroll()
-    unrolled_qasm = result.unrolled_qasm
+    unrolled_qasm = result.dumps()
     check_unrolled_qasm(unrolled_qasm, expected_out)
 
 
@@ -116,7 +116,7 @@ def test_convert_qasm_non_param_gate_def():
 """
     result = load(qasm_in)
     result.unroll()
-    unrolled_qasm = result.unrolled_qasm
+    unrolled_qasm = result.dumps()
     check_unrolled_qasm(unrolled_qasm, expected_out)
 
 
@@ -149,5 +149,5 @@ def test_convert_qasm_recursive_gate_def():
 """
     result = load(qasm_in)
     result.unroll()
-    unrolled_qasm = result.unrolled_qasm
+    unrolled_qasm = result.dumps()
     check_unrolled_qasm(unrolled_qasm, expected_out)
diff --git a/tests/qasm2/test_to_qasm3.py b/tests/qasm2/test_to_qasm3.py
index 1211fcf..ea43ea0 100644
--- a/tests/qasm2/test_to_qasm3.py
+++ b/tests/qasm2/test_to_qasm3.py
@@ -12,32 +12,101 @@
 Module containing unit tests for conversion to qasm3.
 
 """
+import pytest
 
 from pyqasm.entrypoint import load
 from pyqasm.modules.qasm3 import Qasm3Module
 from tests.utils import check_unrolled_qasm
 
+QASM_TEST_DATA = [
+    (
+        """
+OPENQASM 2.0;
+include "qelib1.inc";
+qreg q[1] ;
+qreg qubits  [10]   ;
+creg c[1];
+creg bits   [12]   ;
+        """,
+        """
+OPENQASM 3.0;
+include "stdgates.inc";
+qubit[1] q;
+qubit[10] qubits;
+bit[1] c;
+bit[12] bits;
+        """,
+    ),
+    (
+        """
+OPENQASM 2.0;
+include "qelib1.inc";
+qreg q[2];
+creg c[2];
+measure q->c;
+measure q[0] -> c[1];
+        """,
+        """
+OPENQASM 3.0;
+include "stdgates.inc";
+qubit[2] q;
+bit[2] c;
+c = measure q;
+c[1] = measure q[0];
+        """,
+    ),
+    (
+        """
+OPENQASM 2.0;
+include "qelib1.inc";
+qreg q[1];
+        """,
+        """
+OPENQASM 3.0;
+include "stdgates.inc";
+qubit[1] q;
+        """,
+    ),
+    (
+        """
+OPENQASM 2.0;
+include "qelib1.inc";
+qreg q[5];
+u(1,2,3) q[0];
+sxdg q[0];
+csx q[0], q[1];
+cu1(0.5) q[0], q[1];
+cu3(1,2,3) q[0], q[1];
+rzz(0.5) q[0], q[1];
+rccx q[0], q[1], q[2];
+rc3x q[0], q[1], q[2], q[3];
+c3x q[0], q[1], q[2], q[3];
+c3sqrtx q[0], q[1], q[2], q[3];
+c4x q[0], q[1], q[2], q[3], q[4];
+        """,
+        """
+OPENQASM 3.0;   
+include "stdgates.inc";
+qubit[5] q;
+u(1, 2, 3) q[0];
+sxdg q[0];
+csx q[0], q[1];
+cu1(0.5) q[0], q[1];
+cu3(1, 2, 3) q[0], q[1];
+rzz(0.5) q[0], q[1];
+rccx q[0], q[1], q[2];
+rc3x q[0], q[1], q[2], q[3];
+c3x q[0], q[1], q[2], q[3];
+c3sqrtx q[0], q[1], q[2], q[3];
+c4x q[0], q[1], q[2], q[3], q[4];
+        """,
+    ),
+]
 
-def test_to_qasm3_str():
-    qasm2_string = """
-    OPENQASM 2.0;
-    include "qelib1.inc";
-    qreg q[1];
-    creg c[1];
-    h q;
-    measure q -> c;
-    """
-    result = load(qasm2_string)
-
-    expected_qasm3 = """
-    OPENQASM 3.0;
-    include "stdgates.inc";
-    qubit[1] q;
-    bit[1] c;
-    h q;
-    c = measure q;
-    """
 
+@pytest.mark.parametrize("test_input, expected_qasm3", QASM_TEST_DATA)
+def test_to_qasm3_str(test_input, expected_qasm3):
+    result = load(test_input)
     returned_qasm3 = result.to_qasm3(as_str=True)
     assert isinstance(returned_qasm3, str)
     check_unrolled_qasm(returned_qasm3, expected_qasm3)
diff --git a/tests/qasm3/declarations/test_quantum.py b/tests/qasm3/declarations/test_quantum.py
index 46e7813..04dd3d7 100644
--- a/tests/qasm3/declarations/test_quantum.py
+++ b/tests/qasm3/declarations/test_quantum.py
@@ -46,7 +46,7 @@ def test_qubit_declarations():
 
     result = load(qasm3_string)
     result.unroll()
-    unrolled_qasm = result.unrolled_qasm
+    unrolled_qasm = result.dumps()
 
     check_unrolled_qasm(unrolled_qasm, expected_qasm)
 
@@ -77,7 +77,7 @@ def test_clbit_declarations():
 
     result = load(qasm3_string)
     result.unroll()
-    unrolled_qasm = result.unrolled_qasm
+    unrolled_qasm = result.dumps()
 
     check_unrolled_qasm(unrolled_qasm, expected_qasm)
 
@@ -116,7 +116,7 @@ def test_qubit_clbit_declarations():
 
     result = load(qasm3_string)
     result.unroll()
-    unrolled_qasm = result.unrolled_qasm
+    unrolled_qasm = result.dumps()
 
     check_unrolled_qasm(unrolled_qasm, expected_qasm)
 
diff --git a/tests/qasm3/subroutines/test_subroutines.py b/tests/qasm3/subroutines/test_subroutines.py
index 126727d..5a9692d 100644
--- a/tests/qasm3/subroutines/test_subroutines.py
+++ b/tests/qasm3/subroutines/test_subroutines.py
@@ -130,7 +130,7 @@ def my_function(qubit[4] q) -> bool{
     assert result.num_clbits == 0
     assert result.num_qubits == 4
 
-    print(result.unrolled_qasm)
+    print(result.dumps())
     check_single_qubit_gate_op(result.unrolled_ast, 4, list(range(4)), "h")
 
 
diff --git a/tests/qasm3/test_barrier.py b/tests/qasm3/test_barrier.py
index 5d78768..fd33723 100644
--- a/tests/qasm3/test_barrier.py
+++ b/tests/qasm3/test_barrier.py
@@ -63,7 +63,7 @@ def test_barrier():
     module = load(qasm_str)
     module.unroll()
 
-    check_unrolled_qasm(module.unrolled_qasm, expected_qasm)
+    check_unrolled_qasm(module.dumps(), expected_qasm)
 
 
 def test_barrier_in_function():
@@ -89,7 +89,7 @@ def my_function(qubit[4] a) {
     """
     module = load(qasm_str)
     module.unroll()
-    check_unrolled_qasm(module.unrolled_qasm, expected_qasm)
+    check_unrolled_qasm(module.dumps(), expected_qasm)
 
 
 def test_remove_barriers():
@@ -117,7 +117,7 @@ def test_remove_barriers():
     module = load(qasm_str)
     module.remove_barriers()
 
-    check_unrolled_qasm(module.unrolled_qasm, expected_qasm)
+    check_unrolled_qasm(module.dumps(), expected_qasm)
 
 
 def test_incorrect_barrier():
diff --git a/tests/qasm3/test_format.py b/tests/qasm3/test_format.py
new file mode 100644
index 0000000..1255c96
--- /dev/null
+++ b/tests/qasm3/test_format.py
@@ -0,0 +1,68 @@
+# Copyright (C) 2024 qBraid
+#
+# This file is part of pyqasm
+#
+# Pyqasm is free software released under the GNU General Public License v3
+# or later. You can redistribute and/or modify it under the terms of the GPL v3.
+# See the LICENSE file in the project root or <https://www.gnu.org/licenses/gpl-3.0.html>.
+#
+# THERE IS NO WARRANTY for pyqasm, as per Section 15 of the GPL v3.
+
+"""
+Module containing unit tests for program formatting
+
+"""
+
+from pyqasm.entrypoint import load
+from tests.utils import check_unrolled_qasm
+
+
+def test_comments_removed_from_qasm():
+    qasm3_string = """
+    OPENQASM 3;
+    include "stdgates.inc";
+    // This is a comment
+    qubit q;
+    // This is another comment
+    h q;
+    """
+    expected_qasm3_string = """
+    OPENQASM 3.0;
+    include "stdgates.inc";
+    qubit q;
+    h q;
+    """
+
+    result = load(qasm3_string)
+    actual_qasm3_string = result.formatted_qasm()
+
+    check_unrolled_qasm(actual_qasm3_string, expected_qasm3_string)
+
+
+def test_empty_lines_removed_from_qasm():
+    qasm3_string = """
+    OPENQASM 3.0;
+
+
+    include "stdgates.inc";
+
+
+
+    qubit q;
+    h q;
+
+
+
+    
+    """
+    expected_qasm3_string = """
+    OPENQASM 3.0;
+    include "stdgates.inc";
+    qubit q;
+    h q;
+    """
+
+    result = load(qasm3_string)
+    actual_qasm3_string = result.formatted_qasm()
+
+    check_unrolled_qasm(actual_qasm3_string, expected_qasm3_string)
diff --git a/tests/qasm3/test_gates.py b/tests/qasm3/test_gates.py
index c170fc1..539a9e1 100644
--- a/tests/qasm3/test_gates.py
+++ b/tests/qasm3/test_gates.py
@@ -59,7 +59,7 @@ def test_two_qubit_qasm3_gates(circuit_name, request):
     result.unroll()
     assert result.num_qubits == 2
     assert result.num_clbits == 0
-    print(result.unrolled_qasm)
+    print(result.dumps())
     check_two_qubit_gate_op(result.unrolled_ast, 2, qubit_list, gate_name)
 
 
diff --git a/tests/qasm3/test_if.py b/tests/qasm3/test_if.py
index 7ef5361..d25f908 100644
--- a/tests/qasm3/test_if.py
+++ b/tests/qasm3/test_if.py
@@ -67,7 +67,7 @@ def test_simple_if():
     assert result.num_clbits == 4
     assert result.num_qubits == 4
 
-    check_unrolled_qasm(result.unrolled_qasm, expected_qasm)
+    check_unrolled_qasm(result.dumps(), expected_qasm)
 
 
 def test_complex_if():
@@ -133,8 +133,8 @@ def test_complex_if():
     result.unroll()
     assert result.num_clbits == 8
     assert result.num_qubits == 4
-    print(result.unrolled_qasm)
-    check_unrolled_qasm(result.unrolled_qasm, expected_qasm)
+    print(result.dumps())
+    check_unrolled_qasm(result.dumps(), expected_qasm)
 
 
 def test_incorrect_if():
diff --git a/tests/qasm3/test_loop.py b/tests/qasm3/test_loop.py
index 3238938..7e0c9cd 100644
--- a/tests/qasm3/test_loop.py
+++ b/tests/qasm3/test_loop.py
@@ -61,7 +61,7 @@ def test_convert_qasm3_for_loop():
     assert result.num_qubits == 4
     assert result.num_clbits == 4
 
-    print(result.unrolled_qasm)
+    print(result.dumps())
 
     check_single_qubit_gate_op(result.unrolled_ast, 4, [0, 1, 2, 3], "h")
     check_two_qubit_gate_op(result.unrolled_ast, 3, [(0, 1), (1, 2), (2, 3)], "cx")
diff --git a/tests/qasm3/test_measurement.py b/tests/qasm3/test_measurement.py
index 70220bb..b1fbedb 100644
--- a/tests/qasm3/test_measurement.py
+++ b/tests/qasm3/test_measurement.py
@@ -59,7 +59,7 @@ def test_measure():
 
     module = load(qasm3_string)
     module.unroll()
-    check_unrolled_qasm(module.unrolled_qasm, expected_qasm)
+    check_unrolled_qasm(module.dumps(), expected_qasm)
 
 
 def test_has_measurements():
@@ -125,7 +125,7 @@ def test_remove_measurement():
     module.unroll()
     module.remove_measurements()
 
-    check_unrolled_qasm(module.unrolled_qasm, expected_qasm)
+    check_unrolled_qasm(module.dumps(), expected_qasm)
 
 
 def test_incorrect_measure():
diff --git a/tests/qasm3/test_reset.py b/tests/qasm3/test_reset.py
index 8e7bd54..a9597f4 100644
--- a/tests/qasm3/test_reset.py
+++ b/tests/qasm3/test_reset.py
@@ -52,7 +52,7 @@ def test_reset_operations():
 
     result = load(qasm3_string)
     result.unroll()
-    check_unrolled_qasm(result.unrolled_qasm, expected_qasm)
+    check_unrolled_qasm(result.dumps(), expected_qasm)
 
 
 def test_reset_inside_function():
@@ -76,7 +76,7 @@ def my_function(qubit a) {
 
     result = load(qasm3_string)
     result.unroll()
-    check_unrolled_qasm(result.unrolled_qasm, expected_qasm)
+    check_unrolled_qasm(result.dumps(), expected_qasm)
 
 
 def test_incorrect_resets():
diff --git a/tests/qasm3/test_transformations.py b/tests/qasm3/test_transformations.py
index 9c9352f..76e008b 100644
--- a/tests/qasm3/test_transformations.py
+++ b/tests/qasm3/test_transformations.py
@@ -38,7 +38,7 @@ def test_remove_idle_qubits_qasm3_small():
     assert module.num_qubits == 4
     module.remove_idle_qubits()
     assert module.num_qubits == 2
-    check_unrolled_qasm(module.unrolled_qasm, expected_qasm3_str)
+    check_unrolled_qasm(module.dumps(), expected_qasm3_str)
 
 
 def test_remove_idle_qubits_qasm3():
@@ -88,7 +88,7 @@ def test_remove_idle_qubits_qasm3():
     module.remove_idle_qubits()
     assert module.num_qubits == 7
 
-    check_unrolled_qasm(module.unrolled_qasm, expected_qasm3_str)
+    check_unrolled_qasm(module.dumps(), expected_qasm3_str)
 
 
 def test_reverse_qubit_order_qasm3():
@@ -128,4 +128,4 @@ def test_reverse_qubit_order_qasm3():
 
     module = load(qasm3_str)
     module.reverse_qubit_order()
-    check_unrolled_qasm(module.unrolled_qasm, expected_qasm3_str)
+    check_unrolled_qasm(module.dumps(), expected_qasm3_str)